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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:58:28