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
相关产品推荐
相关产品推荐

