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

React中Canvas滚轮缩放时页面滚动及preventDefault报错问题

问题解决

你的核心问题是同时通过React的onWheel属性和addEventListener绑定了滚轮事件。React默认会把onWheel这类触摸/滚轮事件设为被动监听(passive),哪怕你手动用addEventListener设置了passive: false,React绑定的那个事件依然是被动的,里面调用event.preventDefault()就会触发错误。

修复步骤:

  • 直接删除canvas标签上的onWheel={handleWheel}属性,只保留useEffect里通过原生API绑定的事件,这样就能确保监听是非被动的,preventDefault()可以正常生效。
  • 注意代码里的拼写错误:draggind应该是dragging,这个笔误会导致拖拽状态判断失效,影响缩放逻辑。

修正后的完整代码:

const SCROLL_SENSITIVITY = 0.0005;
const MAX_ZOOM = 10;
const MIN_ZOOM = 0.3;

const [zoom, setZoom] = useState(0.4);
const [dragging, setDragging] = useState(false); // 修正拼写错误
const canvasRef = useRef(null);
const containerRef = useRef(null);

const clamp = (num, min, max) => Math.min(Math.max(num, min), max);

const handleWheel = (event) => {
    event.preventDefault();
    const { deltaY } = event;
    if (!dragging) { // 修正拼写错误
        setZoom((zoom) =>
            clamp(zoom + deltaY * SCROLL_SENSITIVITY * -1, MIN_ZOOM, MAX_ZOOM)
        );
    }
};

useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    
    canvas.addEventListener('wheel', handleWheel, { passive: false });
    return () => {
        canvas.removeEventListener('wheel', handleWheel, { passive: false });
    };
}, [handleWheel]);

return (
    <div ref={containerRef}>
        <canvas 
            ref={canvasRef}
        />
    </div>
);

另外补充一点:如果后续需要处理不同浏览器的滚轮delta值差异,可以考虑对deltaY做归一化处理,但当前场景下先解决核心的preventDefault报错问题即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 03:52:43