如何停止Canvas中多个同时运行的鼠标事件函数
解决Canvas正方形边角拖动后函数持续执行的问题
看起来你遇到的核心问题是重复绑定mousemove事件导致的事件叠加——每次拖动边角时,你都给Canvas添加了新的mousemove监听,但没有在拖动结束后移除它们,所以多次操作后,多个调整函数会同时响应鼠标移动,出现“持续执行”的情况。
下面是具体的修复方案:
1. 修正事件绑定的基础错误
首先,你在canvasClick里调用$('#area').on('mousemove', resize(event))的时候,是立即执行了resize函数,然后把返回值(undefined)绑定给了事件,这完全不符合预期。正确的做法是传递函数引用,不要加括号和参数:
// 错误写法 $('#area').on('mousemove', resize(event)); // 正确写法 $('#area').on('mousemove', resize);
同理,topR、topL等函数的绑定也要改成传递引用的形式。
2. 拖动结束时解绑所有mousemove事件
在up函数里,除了设置isMouseDown和resizing为false,还要移除Canvas上的mousemove监听,这样每次拖动结束后,旧的调整函数就不会再触发了:
function up(event) { isMouseDown = false; resizing = false; // 解绑所有mousemove事件,避免叠加 $('#area').off('mousemove'); console.log("up"); return; }
3. 优化调整逻辑,避免重复绑定
你可以用一个变量来记录当前激活的调整函数,而不是每次判断边角后都绑定新的事件,这样逻辑更清晰,也能减少事件绑定的次数:
比如,新增一个变量currentResizeFn:
var currentResizeFn = null;
然后在resize函数里,更新这个变量,而不是直接绑定事件:
function resize(event) { if (!isMouseDown) return; resizing = true; x = (event.pageX - canvas.offsetLeft); y = (event.pageY - canvas.offsetTop); size = previousSelectedSquare.size; var centreX = previousSelectedSquare.x + size / 2; var centreY = previousSelectedSquare.y + size / 2; // 设置当前的调整函数 if (x > centreX && y < centreY) { currentResizeFn = topR; } else if (x < centreX && y < centreY) { currentResizeFn = topL; } else if (x > centreX && y > centreY) { currentResizeFn = botR; } else if (x < centreX && y > centreY) { currentResizeFn = botL; } else { currentResizeFn = null; resizing = false; return; } }
然后只需要绑定一个全局的mousemove处理函数,在里面调用currentResizeFn:
// 在document ready里绑定一次全局的mousemove处理 $(document).ready(function() { canvas = $('#area')[0]; ctx = canvas.getContext('2d'); $('#area').on('mousedown', canvasClick); $('#area').on('mouseup', up); // 只绑定一次mousemove事件 $('#area').on('mousemove', function(event) { if (currentResizeFn && resizing && isMouseDown) { currentResizeFn(event); } else if (resizing) { resize(event); } }); });
这样就避免了重复绑定mousemove事件,每次拖动只会有一个激活的调整函数在运行。
4. 修复其他小问题
- 你的
botL函数代码不完整,需要补全逻辑,确保和其他边角函数的逻辑一致。 - 在
topL、botR等函数里,不需要重复绑定mouseup事件,因为已经在document ready里绑定过了。
最后,经过这些修改,每次拖动边角时只会有对应的调整函数响应鼠标移动,拖动结束后事件监听会被清理,就不会出现多个函数持续执行的问题了。
内容的提问来源于stack exchange,提问作者Juli
相关产品推荐
相关产品推荐

