HTML Draggable问题:拖拽结束后虚影返回原位置如何解决
解决拖拽重排后虚影返回原位置的问题
这个虚影是浏览器默认拖拽机制生成的元素镜像——哪怕你已经移动了原元素,它依然会绑定初始位置,在dragend时触发回位动画。以下是具体修复方案:
核心修复步骤
- 在
dragstart事件中,必须设置event.dataTransfer.setData(哪怕只是传递空内容),同时指定拖拽行为类型effectAllowed = 'move',让浏览器正确识别拖拽意图 - 可选:用
setDragImage隐藏默认拖拽镜像,彻底消除虚影干扰
修改后的关键代码片段:
song.addEventListener("dragstart", (event) => { draggedElement = event.target; draggedText = draggedElement.textContent; draggedElement.classList.add("dragging"); // 必须设置dataTransfer内容,否则浏览器会保留默认镜像 event.dataTransfer.setData('text/plain', draggedText); // 指定拖拽行为为移动 event.dataTransfer.effectAllowed = 'move'; // 隐藏默认拖拽镜像(用透明空图片实现) const emptyImg = new Image(); event.dataTransfer.setDragImage(emptyImg, 0, 0); });
另外,原代码中dragover事件的元素移动逻辑会在鼠标划过每个元素时频繁触发,建议优化为只在鼠标穿过元素中点时才调整位置,减少不必要的DOM操作:
song.addEventListener("dragover", (event) => { cancelDefault(event); if (!draggedElement || event.target === draggedElement) return; const targetRect = event.target.getBoundingClientRect(); // 计算元素中点,判断插入方向 const midPoint = targetRect.top + targetRect.height / 2; if (event.clientY > midPoint) { event.target.after(draggedElement); } else { event.target.before(draggedElement); } });
完整修复代码
HTML
<div id='song-list' class='title-list'> </div>
CSS
.draggable-song { height: 26px; padding: 4px 8px; border: 1px solid #eee; margin: 4px 0; cursor: grab; } .draggable-song:active { cursor: grabbing; } .dragging { opacity: 0.4; transform: translateX(-9999px); }
JavaScript
let cancelDefault = (e) => { e.preventDefault(); e.stopPropagation(); return false; }; let list = document.getElementById('song-list'); let draggedElement = null; let draggedText = null; let createSongElement = (songData) => { let song = document.createElement('div'); song.classList.add('draggable-song'); song.setAttribute('draggable', true); song.textContent = songData[1]; song.addEventListener("dragstart", (event) => { draggedElement = event.target; draggedText = draggedElement.textContent; draggedElement.classList.add("dragging"); // 修复核心:设置dataTransfer内容 event.dataTransfer.setData('text/plain', draggedText); event.dataTransfer.effectAllowed = 'move'; // 隐藏默认拖拽镜像 const emptyImg = new Image(); event.dataTransfer.setDragImage(emptyImg, 0, 0); }); song.addEventListener("dragend", (event) => { draggedElement?.classList.remove("dragging"); draggedElement = null; cancelDefault(event); }); song.addEventListener("dragenter", cancelDefault); song.addEventListener("drop", cancelDefault); song.addEventListener("dragover", (event) => { cancelDefault(event); if (!draggedElement || event.target === draggedElement) return; const targetRect = event.target.getBoundingClientRect(); const midPoint = targetRect.top + targetRect.height / 2; if (event.clientY > midPoint) { event.target.after(draggedElement); } else { event.target.before(draggedElement); } }); return song; }; let songs = [ ['1234', 'Garden on the kitchen floor'], ['1423', 'Never say never'], ['3251', 'Sitting, waiting, wishing'], ['412', 'Murder on the dance floor'], ['3251421', 'To the moon and back'], ]; songs.forEach((songData) => { let song = createSongElement(songData); list.appendChild(song); });
内容的提问来源于stack exchange,提问作者Mirror318
相关产品推荐
相关产品推荐

