React中使用fabric.js如何通过onClick事件正常添加canvas对象
问题原因
- 你把fabric画布初始化逻辑写在组件函数顶层,React函数组件每次重渲染都会重新执行函数体,这会反复创建全新的fabric画布实例,这些新实例并没有正确绑定到页面上实际渲染的canvas DOM节点。点击事件触发时,你操作的是脱离真实DOM的无效实例,添加的矩形自然不会显示在页面上。
- fabric画布初始化必须等对应的canvas DOM元素挂载到页面后再执行,直接在函数顶层执行初始化时机不对,大概率会拿到还没完成渲染的DOM,导致初始化异常。
修复方案
用useRef存储fabric画布实例,在DOM挂载完成的useEffect钩子里只做一次画布初始化,后续点击事件直接操作ref中保存的有效实例即可,修复后的完整代码如下:
import { useEffect, useRef } from 'react'; import { fabric } from 'fabric'; const Canvasbody = () => { const canvasRef = useRef(null); useEffect(() => { // DOM挂载完成后初始化画布,仅执行一次 canvasRef.current = new fabric.Canvas('canvas-main'); // 组件卸载时销毁实例,避免内存泄漏 return () => { canvasRef.current?.dispose(); canvasRef.current = null; } }, []); const handleAddRect = () => { if (!canvasRef.current) return; const rect = new fabric.Rect({ height: 280, width: 200, fill: 'yellow', left: 20, top: 20 }); canvasRef.current.add(rect); // 若遇到添加后不刷新的情况,放开下面这行强制重绘 // canvasRef.current.renderAll(); } return ( <> <canvas style={{ border: 'solid 1px #555' }} id="canvas-main" width="600px" height="600px" /> <button onClick={handleAddRect}>Click me</button> </> ); }; export default Canvasbody;
注意:不要在组件函数顶层直接调用new fabric.Canvas(),否则只要组件发生重渲染就会重复创建实例,不仅会导致操作不生效,还会造成内存泄漏。
内容的提问来源于stack exchange,提问作者Sohaib Ashraf
相关产品推荐
相关产品推荐

