鼠标按下可跟随移动,但抬起无法移除mousemove事件的拖拽问题
问题解决:SVG元素拖拽后无法停止跟随的问题
问题原因
核心问题是:每次添加mousemove事件时使用匿名函数,移除事件时又创建了新的匿名函数,这两个函数是不同的引用,导致removeEventListener找不到要移除的目标,鼠标抬起后事件依然生效,元素持续跟随移动。
修复方案
把mousemove的处理函数提取为具名函数,确保添加和移除用同一个函数引用;同时优化拖拽逻辑,添加鼠标与元素的偏移量计算,避免拖拽时元素跳变。
修改后的完整代码
createBom() { let bom = null; this.data.forEach((item) => { bom = document.createElementNS("http://www.w3.org/2000/svg", "use"); bom.setAttributeNS( "http://www.w3.org/1999/xlink", "xlink:href", `#${item.id}` ); bom.setAttribute("width", item.width); bom.setAttribute("height", item.height); bom.setAttribute("x", item.x); bom.setAttribute("y", item.y); bom.setAttribute("cursor", "move"); // 定义具名的移动处理函数 const handleMouseMove = (e) => { this.move(e, bom, item); }; // 鼠标抬起事件:移除移动监听 const handleMouseUp = () => { console.log("鼠标抬起"); document.removeEventListener("mousemove", handleMouseMove); document.removeEventListener("mouseup", handleMouseUp); }; // 鼠标按下事件:添加移动监听和抬起监听 bom.addEventListener("mousedown", (e) => { console.log("鼠标按下"); // 记录鼠标与元素左上角的偏移量,优化拖拽体验 item.offsetX = e.clientX - parseFloat(bom.getAttribute("x")); item.offsetY = e.clientY - parseFloat(bom.getAttribute("y")); document.addEventListener("mousemove", handleMouseMove); // 将mouseup绑定到document,避免鼠标移出元素后无法触发抬起 document.addEventListener("mouseup", handleMouseUp); }); this.parent.appendChild(bom); }); } // 优化move函数实现(处理偏移量) move(e, bom, item) { const newX = e.clientX - item.offsetX; const newY = e.clientY - item.offsetY; bom.setAttribute("x", newX); bom.setAttribute("y", newY); // 同步更新data中的坐标 item.x = newX; item.y = newY; }
关键修改点
- 使用**具名函数
handleMouseMove**作为mousemove事件的处理函数,保证添加和移除事件时引用一致。 - 将
mouseup事件绑定到document,避免鼠标拖拽时移出元素范围后无法触发抬起操作。 - 添加鼠标与元素的偏移量计算,解决拖拽时元素瞬间跳变到鼠标位置的问题。
- 在
mouseup触发后,同时移除自身的监听,防止多次绑定导致的异常。
内容的提问来源于stack exchange,提问作者ark
相关产品推荐
相关产品推荐

