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

React TypeScript问题:Canvas动画与onMouseMove事件冲突

解决Canvas动画与鼠标交互冲突的思路和方案

问题根源分析

你的代码核心冲突点在于:

  • 动画循环(requestAnimationFrame)持续清空并重绘canvas,鼠标交互的命中检测逻辑未与动画循环同步,每次重绘后无法正确追踪目标矩形状态。
  • 鼠标移动事件的坐标计算未考虑canvas的实际渲染偏移,导致命中判断出错。

具体修复步骤

1. 同步鼠标状态与动画循环

用React状态管理鼠标位置和悬停状态,确保动画重绘时能获取最新的鼠标数据:

const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
const [isHovering, setIsHovering] = useState(false);

2. 修正鼠标坐标计算

在onMouseMove事件中,通过getBoundingClientRect()获取canvas实际位置,计算相对canvas的坐标:

const handleMouseMove = (e: React.MouseEvent<HTMLCanvasElement>) => {
  const rect = e.currentTarget.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const y = e.clientY - rect.top;
  setMousePos({ x, y });
};

3. 在动画循环中做命中检测

每次重绘前,结合当前动画帧的矩形位置和鼠标坐标判断悬停状态,再根据状态绘制对应样式:

const animate = () => {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  
  // 绘制动画矩形
  ctx.fillStyle = 'blue';
  ctx.fillRect(animatedX, 50, 100, 100);
  
  // 定义目标矩形参数
  const targetRect = { x: 200, y: 200, width: 100, height: 100 };
  // 判断鼠标是否在目标矩形范围内
  const hovering = 
    mousePos.x >= targetRect.x &&
    mousePos.x <= targetRect.x + targetRect.width &&
    mousePos.y >= targetRect.y &&
    mousePos.y <= targetRect.y + targetRect.height;
  setIsHovering(hovering);
  
  // 根据悬停状态切换目标矩形样式
  ctx.fillStyle = hovering ? 'red' : 'green';
  ctx.fillRect(targetRect.x, targetRect.y, targetRect.width, targetRect.height);
  
  // 更新动画矩形位置
  setAnimatedX(prev => (prev + 2) % canvas.width);
  requestId.current = requestAnimationFrame(animate);
};

4. 清理动画循环

组件卸载时取消requestAnimationFrame,避免内存泄漏:

useEffect(() => {
  requestId.current = requestAnimationFrame(animate);
  return () => {
    cancelAnimationFrame(requestId.current);
  };
}, []);

核心思路总结

  • 动画循环与鼠标交互需共享同一套状态,保证每次重绘都基于最新鼠标状态做判断。
  • 鼠标坐标必须转换为canvas内部相对坐标,避免页面布局偏移导致的命中错误。
  • 所有视觉变化都在动画循环内完成,确保渲染一致性,避免React状态更新与手动canvas绘制的冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 02:52:10