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

如何停止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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:16:14