You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多窗口拖拽异常问题:首个可拖拽窗口释放鼠标后无法停止拖拽

问题分析与解决方案

嗨,刚接触JS/HTML/CSS就能实现窗口标题栏拖拽的效果,已经做得很棒啦!咱们来拆解下你遇到的问题:

你猜的没错,问题核心确实在拖拽结束的document.onmouseup代码段里。每次调用makeDragable函数时,你都用document.onmouseup = function(...)直接赋值新的处理函数——这会彻底覆盖掉之前绑定的函数。当你第二次调用makeDragable处理第二个窗口后,第一个窗口的mouseup逻辑就被替换了,导致第一个窗口释放鼠标时,没法移除它的mousemove监听,自然就停不下来拖拽了。

修复后的代码

只需要修改拖拽结束的绑定方式,用addEventListener替代直接赋值,就能让多个窗口的拖拽结束逻辑共存:

// Draggable Content JS
function makeDragable(dragHandle, dragTarget) {
 let dragObj = null; // 要拖动的对象
 let xOffset = 0; // 防止拖动时对象跳转到鼠标位置的偏移量
 let yOffset = 0;

 // 提前获取DOM元素,避免重复查询
 const handle = document.querySelector(dragHandle);
 const target = document.querySelector(dragTarget);

 handle.addEventListener("mousedown", startDrag, true);
 handle.addEventListener("touchstart", startDrag, true);

 /* 设置偏移参数并开始监听鼠标移动 */
 function startDrag(e) {
 e.preventDefault();
 e.stopPropagation();
 dragObj = target;
 dragObj.style.position = "absolute";
 let rect = dragObj.getBoundingClientRect();
 if (e.type=="mousedown") {
 xOffset = e.clientX - rect.left;
 yOffset = e.clientY - rect.top;
 window.addEventListener('mousemove', dragObject, true);
 } else if(e.type=="touchstart") {
 xOffset = e.targetTouches[0].clientX - rect.left;
 yOffset = e.targetTouches[0].clientY - rect.top;
 window.addEventListener('touchmove', dragObject, true);
 }
 }

 /* 拖动对象逻辑 */
 function dragObject(e) {
 e.preventDefault();
 e.stopPropagation();
 if(dragObj == null) {
 return;
 } else if(e.type=="mousemove") {
 dragObj.style.left = e.clientX-xOffset +"px";
 dragObj.style.top = e.clientY-yOffset +"px";
 } else if(e.type=="touchmove") {
 dragObj.style.left = e.targetTouches[0].clientX-xOffset +"px";
 dragObj.style.top = e.targetTouches[0].clientY-yOffset +"px";
 }
 }

 /* 结束拖动 - 修改核心部分 */
 function endDrag(e) {
 if (dragObj) {
 dragObj = null;
 window.removeEventListener('mousemove', dragObject, true);
 window.removeEventListener('touchmove', dragObject, true);
 }
 }

 // 用addEventListener绑定,避免覆盖之前的处理函数
 document.addEventListener('mouseup', endDrag, true);
 document.addEventListener('touchend', endDrag, true);
}

makeDragable('#handle_1', '#moveable_1')
makeDragable('#handle_2', '#moveable_2')

关键修改点说明

  1. 替换事件绑定方式:把document.onmouseup = function(...)改成document.addEventListener('mouseup', endDrag, true),这样每个窗口的endDrag函数都会被独立绑定,不会被后续调用覆盖。
  2. 补充触摸事件处理:同时给touchend绑定了结束逻辑,保证触摸设备上的拖拽也能正常停止。
  3. 优化DOM查询:提前把拖拽手柄和目标元素存到变量里,避免每次事件触发时重复查询DOM,小幅度提升性能。

如果以后担心多个窗口同时拖拽的冲突,可以加一个全局变量跟踪当前正在拖拽的对象,在新拖拽开始时自动结束之前的拖拽过程,不过目前你的需求场景下,上面的修复已经完全够用啦。

内容的提问来源于stack exchange,提问作者elliott hall

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 23:04:06