Vue3集成Fabric.js开发电子白板:书写200次后卡顿求助
Fabric.js电子白板书写200次后卡顿问题排查与优化
核心问题分析
你怀疑的这段代码确实是卡顿的核心诱因:每次绘制完成后都调用canvas.toJSON()全量序列化整个画布,随着路径数量突破200+,序列化的时间开销会线性增长;同时全量保存画布状态到历史记录会快速占用内存,触发频繁的垃圾回收,最终导致操作卡顿。
针对性优化方案
1. 替换全量序列化为增量记录
不要每次都序列化整个画布,只记录本次新增路径的状态,大幅减少计算开销:
this.canvas.add(pathObj) // 仅序列化当前新增的路径,而非全画布 const pathState = pathObj.toJSON(['eventInfo']) const action = { type: 'draw', data: pathState // 传递单个路径的增量数据 } // 调整getState逻辑,基于现有状态合并增量 this.state = this.getState(this.state, action) // 仅保存增量操作到历史,而非全量状态 this.saveHistory(action)
后续恢复历史时,基于初始状态逐个应用增量操作即可,避免全量序列化的性能损耗。
2. 合并连续手绘路径
Fabric.js中每个Path对象都会占用渲染资源,连续的手绘路径(比如一笔画的线条)可以合并成单个Path对象,减少画布上的对象总数:
// 示例:合并同属性的连续路径 const lastPath = this.canvas.getObjects().pop() if (lastPath && lastPath.type === 'path' && lastPath.stroke === pathObj.stroke) { // 合并路径指令 lastPath.path.push(...pathObj.path) lastPath.setCoords() this.canvas.renderAll() // 无需新增对象,直接更新历史记录 return } // 不满足合并条件时再新增路径 this.canvas.add(pathObj)
3. 优化历史记录存储
放弃保存完整画布状态快照,改为存储操作指令(比如draw、delete、modify)及对应数据,历史记录的内存占用会骤降,同时回退/重做操作也更高效。
4. 渲染性能调优
- 开启Fabric.js的
preserveObjectStacking时注意控制层级,避免不必要的重排 - 将静态PDF背景转为Image对象添加到画布底层,避免PDF渲染与手绘路径的性能冲突
调试建议
用浏览器DevTools的Performance面板录制卡顿场景,查看canvas.toJSON和saveHistory的执行耗时,确认是否是JS线程阻塞导致的卡顿;同时查看Rendering面板,检查是否有过度绘制的情况。
内容的提问来源于stack exchange,提问作者stchen
相关产品推荐
相关产品推荐

