前言:前幾天沒事干寫了個小網站,打算用原生的javascript實現元素的拖動,但是事情並沒有想象的那么順利,首先是實現了拖動的元素卡的不能再卡,簡直不能夠,上圖~~
看見沒?這就是效果,簡直讓人欲哭無淚啊,查了大量的資料也無濟於事,根本就沒有人會遇到過這個問題,但是經過N次試驗,終於找到了原因——竟然是我給這個元素添加了transition屬性導致的,元凶:
去掉這個屬性之后,就變得完全不一樣了
至於原因,我現在也不知道為什么,很無奈╮(╯▽╰)╭
接下來就是性能優化了,我原來的實現方式是給元素添加一個mousemove事件,然后判斷事件對象的buttons是否為1,如果是1的話表明此時左鍵按下,然后記錄此時鼠標的x和y的坐標,當下次觸發mousemove事件的時候用當前鼠標的位置減去上次記錄的鼠標的位置就是鼠標移動的距離,然后用元素當前的位置加上鼠標移動的距離就實現了拖動,代碼如下:
//實現拖動 var lastClientX = 0; var lastClientY = 0; var count = 0; addCommandCard.addEventListener('mousemove', function() { if(arguments[0].buttons == 1) { addCommandCard.style.cursor = "default"; arguments[0].preventDefault(); if(count == 0) { lastClientX = arguments[0].clientX; lastClientY = arguments[0].clientY; count++; } else { addCommandCard.style.left = addCommandCard.offsetLeft + arguments[0].clientX - lastClientX + "px"; addCommandCard.style.top = addCommandCard.offsetTop + arguments[0].clientY - lastClientY + "px"; lastClientX = arguments[0].clientX; lastClientY = arguments[0].clientY; count++; } } });
今天看了個實現拖動的代碼,基本思路是,給元素添加mousedown事件,在這個事件處理程序中,首先記錄當前鼠標的位置與元素的offsetLeft和offsetTop的差值,然后給document添加mousemove和mouseup事件,在document的mousemove事件中,將元素的left設置為當前鼠標X坐標減去上面記錄的鼠標X坐標和元素offsetLeft的差值,top值設置為當前鼠標Y坐標減去上面記錄的鼠標Y坐標和元素offsetTop的差值,在mouseup事件中,設置document的mousemove和mouseup為null,上面的話可能有些拗口,通俗點說就是首先記錄元素的左邊框和鼠標X坐標的差值,然后記錄元素的上邊框和鼠標Y坐標的差值,在鼠標移動的時候將元素的左邊框的值設置為鼠標當前X坐標的值減去鼠標和元素左邊框之間的相對距離,上邊框類似,因為在元素拖動的過程中,鼠標和元素的相對位置始終沒有發生變化,所以只要用鼠標當前的位置減去鼠標和元素之間的相對距離就是元素拖動后的位置,代碼:
//實現拖動 addCommandCard.addEventListener('mousedown', function() { arguments[0].preventDefault(); var disX = arguments[0].clientX - addCommandCard.offsetLeft; var disY = arguments[0].clientY - addCommandCard.offsetTop; document.onmousemove = function() { addCommandCard.style.left = arguments[0].clientX - disX + 'px'; addCommandCard.style.top = arguments[0].clientY - disY + 'px'; } document.onmouseup = function() { document.onmousemove = null; document.onmouseup = null; } });
總結:在chrome中測試結果表明,兩種拖動方式都可以穩定在60fps,總得來說,差別不大,但是第一種有比較慢明顯的缺點,首先,第一種給元素添加了mousemove事件,那就意味着不管元素當前是否拖動,只要有鼠標移動到元素上,這個事件就不斷的觸發,雖然只有一條判斷語句,但是造成性能的白白浪費,而第二種是添加了mousedown事件,只有鼠標按下的時候才會觸發,所以沒有這個問題,但是,如果在別處給document指定了mousemove和mouseup事件,那么在元素拖動開始和結束之后,這些事件處理程序會變得無效,因為覆蓋的原因,但是可以通過DOM2級事件處理程序來解決,不算大問題



