JavaScript 原生拖拽是指添加一些代碼和事件,使得網(wǎng)頁(yè)中的元素可以被鼠標(biāo)拖動(dòng)。這是一個(gè)非常常見(jiàn)的功能,可以應(yīng)用到各種場(chǎng)景中,比如圖像拖拽、表格排序等等。使用 JavaScript 原生拖拽也是開(kāi)發(fā)中常用的技巧,下面我們來(lái)了解一下如何使用。
首先,我們需要在元素上綁定一些事件。比如,我們可以在元素上添加一個(gè) mousedown 事件,用來(lái)激活拖拽。當(dāng)用戶點(diǎn)擊元素并準(zhǔn)備拖拽時(shí),就會(huì)觸發(fā)該事件。接下來(lái),我們需要為 document 添加一些事件,用來(lái)跟蹤鼠標(biāo)位置。這些事件包括 mousemove 和 mouseup。mousemove 事件可以顯示當(dāng)前鼠標(biāo)的位置,而 mouseup 事件可以停止拖拽并釋放元素。
let dragObj = null; let mouseOffset = null; element.addEventListener('mousedown', function(e) { dragObj = this; mouseOffset = { x: e.clientX - this.offsetLeft, y: e.clientY - this.offsetTop }; }); document.addEventListener('mousemove', function(e) { if (dragObj) { dragObj.style.left = (e.clientX - mouseOffset.x) + 'px'; dragObj.style.top = (e.clientY - mouseOffset.y) + 'px'; } }); document.addEventListener('mouseup', function(e) { dragObj = null; mouseOffset = null; });
上面的代碼中,我們首先定義了兩個(gè)變量 dragObj 和 mouseOffset。dragObj 存儲(chǔ)當(dāng)前拖拽的元素,而 mouseOffset 存儲(chǔ)當(dāng)前鼠標(biāo)與元素左上角的偏移量。當(dāng)用戶點(diǎn)擊元素并準(zhǔn)備拖拽時(shí),mousedown 事件就會(huì)把當(dāng)前元素存儲(chǔ)在 dragObj 中,并計(jì)算出鼠標(biāo)與元素左上角的位置差。
接下來(lái),我們?yōu)?document 添加 mousemove 事件。在這個(gè)事件中,我們判斷 dragObj 是否存在,如果存在,則將元素的位置設(shè)為鼠標(biāo)的位置減去偏移量。這樣就可以實(shí)現(xiàn)元素跟隨鼠標(biāo)移動(dòng)了。最后,在 mouseup 事件中,我們將 dragObj 和 mouseOffset 設(shè)為 null,表示結(jié)束拖拽。
JavaScript 原生拖拽可以實(shí)現(xiàn)很多有趣的效果。比如,我們可以應(yīng)用在圖片的拖拽上,從而實(shí)現(xiàn)酷炫的畫廊效果。我們可以把下面的代碼放在 HTML 中:
在 CSS 中,我們可以設(shè)置圖片樣式:
.gallery img { width: 200px; height: 200px; margin: 10px; box-shadow: 0 0 10px rgba(0,0,0,0.5); }
最后,我們添加一些 JavaScript 代碼,實(shí)現(xiàn)原生拖拽效果:
let gallery = document.querySelector('.gallery'); gallery.addEventListener('dragstart', function(e) { e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('text/plain', null); dragObj = e.target; }); gallery.addEventListener('dragover', function(e) { e.preventDefault(); }); gallery.addEventListener('drop', function(e) { e.preventDefault(); let dropObj = e.target; let temp = document.createElement('div'); dropObj.parentNode.insertBefore(temp, dropObj); dragObj.parentNode.insertBefore(dropObj, dragObj); temp.parentNode.insertBefore(dragObj, temp); temp.parentNode.removeChild(temp); });
在上面的代碼中,我們?yōu)閳D片元素添加了一個(gè) dragstart 事件,用來(lái)激活拖拽。在該事件中,我們使用了 e.dataTransfer 對(duì)象,該對(duì)象包含了一些方法和屬性,可以用來(lái)傳遞拖拽數(shù)據(jù)。在這里,我們?cè)O(shè)置了拖拽效果為 move,并傳遞了一個(gè)空值。
接下來(lái),我們?yōu)?gallery 添加了 dragover 和 drop 事件。dragover 事件用來(lái)防止默認(rèn)行為,而 drop 事件則用來(lái)處理拖拽完成后的邏輯。在 drop 事件中,我們獲得了放置的目標(biāo)元素 dropObj,并創(chuàng)建了一個(gè)臨時(shí)元素 temp。然后,我們使用 insertBefore() 方法將 dropObj 移動(dòng)到了 dragObj 的前面,然后再使用 insertBefore() 把 dragObj 移動(dòng)到了 temp 的前面。最后,我們用 removeChild() 方法將 temp 刪除。
上面的代碼演示了如何使用原生拖拽實(shí)現(xiàn)一個(gè)酷炫的畫廊效果。在實(shí)踐中,我們還可以應(yīng)用原生拖拽到更多的應(yīng)用場(chǎng)景,比如表格排序、拖放之類的。希望這篇文章對(duì)大家有所幫助。