FabricJs:从 JSON (patternSourceCanvas) 保存和加载动态模式

FabricJs: Saving and loading dynamic patterns from JSON (patternSourceCanvas)

我在保存和加载应用于对象的 dynamic patterns 时遇到问题。

我在网上搜索过这个问题的解决方案,但无济于事。我明白why it is happening,但不明白如何解决。

这基本上就是我正在做的...

  1. 正在将动态模式应用于对象。
  2. 将 canvas 保存到 MongoDB 使用...'JSON.stringify(canvas.toJSON([...]))'
  3. 正在使用 'loadFromJSON'
  4. 加载 canvas
  5. 获取错误'Uncaught ReferenceError: patternSourceCanvas is not defined'

我在这个问题上发现的一切都可以追溯到至少 2 年前 (some even 2013),没有可靠的代码示例。

更新

这是我用来在路径上应用模式的函数...

function applyPatternOnPath(p, image, width, patternRepeat, patternPadding) {

    if (patternRepeat) {
      var r = 'repeat'
    } else {
      var r = 'no-repeat'
    }

    fabric.Image.fromURL(image, function(img) {

      var padding = 0 + patternPadding;

      img.scaleToWidth(width);

      var patternSourceCanvas = new fabric.StaticCanvas();

      patternSourceCanvas.add(img);
      patternSourceCanvas.renderAll();

      var pattern = new fabric.Pattern({
        source: function() {
          patternSourceCanvas.setDimensions({
            width: img.getScaledWidth() + padding,
            height: img.getScaledHeight() + padding
          });
          patternSourceCanvas.renderAll();
          return patternSourceCanvas.getElement();
        },
        repeat: r
      });

      p.set('fill', pattern);
      canvas.renderAll();

    }, { crossOrigin: 'Anonymous' });
  }

我已经通过一些变通方法解决了我的问题。我不确定这是否是 "correct" 处理使用 JSON 保存的动态模式的方法,但它对我有用。

这是我正在做的...

  1. 正在将动态图案应用到对象上。
  2. 就在将 canvas(JSON 字符串)保存到 MongoDB 之前,我正在做两件事...

    a) 在名为 'canvasLayers'.

    的 mongoDB 文档的字段之一上保存对象信息(包括模式 src、宽度、填充等)

    b) 通过将 'fill' 属性 设置为“”来清除应用了动态模式的路径的所有 'fill' 属性。

    所以 JSON 在保存到数据库时不包含任何模式信息。

  3. 加载以前保存的 canvas 时,我 re-applying 基于保存在每个对象的 'canvasLayers' 字段中的模式信息的模式。

基本上,我不是用 JSON 字符串保存模式信息,而是将模式数据存储在一个单独的对象(mongodb 字段),然后 re-applying canvas 加载时的模式。

使用以下代码将图像源转换为 base 64 格式并存储并重新打开。

//override toObject of fabric.Pattern
var toFixed = fabric.util.toFixed;
fabric.Pattern.prototype.toObject = function(propertiesToInclude) {
  var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,
    source, object;
  if (typeof this.source === "function") {
    source = String(this.source);
  } else if (typeof this.source.src === "string") {
    source = this.source.src;
  } else if (typeof this.source === "object" && this.source.toDataURL) {
    source = this.source.toDataURL();
  }
  object = {
    type: "pattern",
    source: source,
    repeat: this.repeat,
    crossOrigin: this.crossOrigin,
    offsetX: toFixed(this.offsetX, NUM_FRACTION_DIGITS),
    offsetY: toFixed(this.offsetY, NUM_FRACTION_DIGITS),
    patternTransform: this.patternTransform ? this.patternTransform.concat() : null
  };
  fabric.util.populateWithProperties(this, object, propertiesToInclude);
  return object;
};



var imageUrl = 'https://upload.wikimedia.org/wikipedia/commons/2/22/Wikimapia_logotype.svg';
var canvas = new fabric.Canvas('canvas');
var rect = new fabric.Rect({
  width: 200,
  height: 200,
  strokeWidth: 2,
  stroke: '#000'
})
canvas.add(rect);

fabric.Image.fromURL(imageUrl, function(img) {
  //alert('t' + img);
  console.log('img', img);
  img.scaleToHeight(200);
  var patternSourceCanvas = new fabric.StaticCanvas();
  patternSourceCanvas.add(img);
  patternSourceCanvas.setDimensions({
    width: img.getWidth(),
    height: img.getHeight()
  });
  patternSourceCanvas.renderAll();
  var pattern = new fabric.Pattern({
    source: patternSourceCanvas.getElement()
  });
  rect.fill = pattern;
  canvas.renderAll();
}, {
  crossOrigin: 'annonymous'
});

$('#loadjson').on('click', function() {
  var json = canvas.toJSON();
  console.log('json', json['objects']);
  canvas.clear();
  setTimeout(function() {
    canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));
  }, 3000)
})

Css

canvas{
  border:2px solid #000;
}

Html :

<canvas id="canvas" width="300" height="300"></canvas><br>
<button  id="loadjson">loadfromjson </button>


<script src='https://www.multicastr.com/imageeditor/assets/js/fabric.unmin.js'></script>

<script src="https://www.multicastr.com/user/js/jquery.min.js"></script>