FabricJs动态图案(patternSourceCanvas)JSON保存加载问题求助
解决Fabric.js加载动态图案时
patternSourceCanvas is not defined的问题 我明白你遇到的困扰——用Fabric.js给对象应用动态Canvas图案后,序列化保存到MongoDB,加载时却触发Uncaught ReferenceError: patternSourceCanvas is not defined错误。这个问题的核心原因你已经清楚:JSON无法序列化DOM元素(比如你的patternSourceCanvas),所以保存的JSON里只留下了变量名,没有实际的画布内容,加载时自然找不到对应的对象。
下面是我实际解决这类问题的具体方案,分序列化和反序列化两步处理:
解决思路:自定义序列化与反序列化逻辑
我们需要手动把动态图案的Canvas内容转成可序列化的格式(比如Base64字符串),加载时再将其还原为Canvas元素,重新生成Pattern对象。
1. 保存前:把图案源转为Base64序列化
在调用canvas.toJSON()之前,遍历画布上的所有对象,检查是否包含Pattern填充,然后将图案源Canvas转成Base64字符串,并把这个自定义属性加入序列化白名单:
// 遍历画布对象,处理带Pattern填充的元素 canvas.getObjects().forEach(obj => { // 检查对象的fill是否为Pattern类型 if (obj.fill && obj.fill.type === 'pattern') { // 将图案源Canvas转为Base64格式的图片数据 obj.fill.sourceCanvasData = obj.fill.sourceCanvas.toDataURL(); } }); // 序列化时,把自定义的sourceCanvasData属性加入白名单 const canvasJson = JSON.stringify(canvas.toJSON(['sourceCanvasData'])); // 之后将canvasJson保存到MongoDB即可
2. 加载时:还原图案源Canvas
使用loadFromJSON加载后,在回调函数里遍历对象,把Base64数据还原为Canvas,重新创建Pattern并赋值给对象:
// 从MongoDB获取保存的JSON字符串 const savedCanvasJson = /* 你的MongoDB读取逻辑 */; canvas.loadFromJSON(savedCanvasJson, () => { // 先渲染一次基础内容 canvas.renderAll(); // 遍历对象恢复动态图案 canvas.getObjects().forEach(obj => { if (obj.fill && obj.fill.sourceCanvasData) { // 创建一个新的StaticCanvas作为图案源 const patternCanvas = new fabric.StaticCanvas(); // 从Base64加载图片到新Canvas fabric.Image.fromURL(obj.fill.sourceCanvasData, img => { patternCanvas.add(img); patternCanvas.renderAll(); // 重新创建Pattern对象,保留原有的重复设置 const restoredPattern = new fabric.Pattern({ source: patternCanvas.getElement(), repeat: obj.fill.repeat || 'repeat' }); // 给对象设置恢复后的Pattern填充 obj.set('fill', restoredPattern); // 再次渲染画布更新显示 canvas.renderAll(); }); } }); });
3. 额外注意事项
- 确保图案状态最新:如果你的动态图案是实时修改的,一定要在保存前确保
patternSourceCanvas已经渲染了最新内容,否则保存的Base64会是旧的图案。 - 避免重复处理:可以在序列化前检查
obj.fill.sourceCanvasData是否已存在,防止多次序列化导致数据冗余。 - Canvas类型适配:如果你的图案源是
fabric.DynamicCanvas,可以根据需求调整为DynamicCanvas而非StaticCanvas。
内容的提问来源于stack exchange,提问作者Serks
相关产品推荐
相关产品推荐

