database - Fabric.js - 如何使用自定义属性在服务器上保存 Canvas

标签 database json savechanges fabricjs

我希望能够将当前 Canvas 的状态保存到服务器端数据库,可能作为 JSON 字符串,然后使用 loadFromJSON 恢复它。通常,这很容易使用:

var canvas = new fabric.Canvas();
function saveCanvas() {
    // convert canvas to a json string
    var json = JSON.stringify( canvas.toJSON() );

    // save via xhr
    $.post('/save', { json : json }, function(resp){ 
        // do whatever ...
    }, 'json');
}

然后

function loadCanvas(json) {

  // parse the data into the canvas
  canvas.loadFromJSON(json);

  // re-render the canvas
  canvas.renderAll();

  // optional
  canvas.calculateOffset();
}

不过,我还使用内置 Object#set 方法在要添加到 Canvas 的织物对象上设置了一些自定义属性:

// get some item from the canvas
var item = canvas.item(0);

// add misc properties
item.set('wizard', 'gandalf');
item.set('hobbit', 'samwise');

// save current state
saveCanvas();

问题是,当我在服务器端检查请求时,我发现我的自定义属性没有从 Canvas 中解析出来并与其他所有内容一起发送。这可能与 toObject 方法如何删除对象类中不是默认属性的任何内容有关。解决这个问题的好方法是什么,这样我就可以从服务器发送的 JSON 字符串中保存 恢复 Canvas ,并且恢复的 Canvas 也将包括我的自定义属性?谢谢。

最佳答案

好问题。

如果您要向对象添加自定义属性,那么这些对象可能在某些方面是“特殊的”。似乎对它们进行子类化是一个合理的解决方案。

例如,下面是我们如何子类化 fabric.Image成一个命名的图像。然后,这些图像对象可能具有“Gandalf”或“Samwise”之类的名称。

fabric.NamedImage = fabric.util.createClass(fabric.Image, {

  type: 'named-image',

  initialize: function(element, options) {
    this.callSuper('initialize', element, options);
    options && this.set('name', options.name);
  },

  toObject: function() {
    return fabric.util.object.extend(this.callSuper('toObject'), { name: this.name });
  }
});

首先,我们给这些对象一个类型。 loadFromJSON 使用此类型自动调用 fabric.<type>.fromObject方法。在这种情况下,它将是 fabric.NamedImage.fromObject .

然后我们覆盖initialize (构造函数)实例方法,在初始化对象时也设置“name”属性(如果给定了该属性)。

然后我们覆盖toObject在返回的对象中包含“名称”的实例方法(这是结构中对象序列化的基石)。

最后,我们还需要实现 fabric.NamedImage.fromObject我之前提到过,所以 loadFromJSON会知道在 JSON 解析期间调用哪个方法:

fabric.NamedImage.fromObject = function(object, callback) {
  fabric.util.loadImage(object.src, function(img) {
    callback && callback(new fabric.NamedImage(img, object));
  });
};

我们在此处加载图像(来自“object.src”),然后创建 fabric.NamedImage 的实例出它。请注意,此时构造函数已经处理了“name”设置,因为我们之前覆盖了“initialize”方法。

我们还需要指定 fabric.NamedImage是一个异步“类”,这意味着它的 fromObject不返回实例,而是将其传递给回调:

fabric.NamedImage.async = true;

现在我们可以尝试一下:

// create image element
var img = document.createElement('img');
img.src = 'https://www.google.com/images/srpr/logo3w.png';

// create an instance of named image
var namedImg = new fabric.NamedImage(img, { name: 'foobar' });

// add it to canvas
canvas.add(namedImg);

// save json
var json = JSON.stringify(canvas);

// clear canvas
canvas.clear();

// and load everything from the same json
canvas.loadFromJSON(json, function() {

  // making sure to render canvas at the end
  canvas.renderAll();

  // and checking if object's "name" is preserved
  console.log(canvas.item(0).name);
});

关于database - Fabric.js - 如何使用自定义属性在服务器上保存 Canvas ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11272772/

相关文章:

database - 如何使用 Selenium 进行数据库测试?

javascript - 获取天气预报数据以加载到 amcharts 数据加载器中

java - 如何在Java中解析JSON

linux - 我可以使用键盘快捷键在 Linux 上的 Matlab 中保存工作吗?

entity-framework - Entity Framework SaveChanges() 在不同的 DbContext 中插入不必要的行

c++ - 制作一个具有两个固定长度和一个可变长度的 3D vector

PHP: 找不到数据库

database - 逻辑 : Best way to sample & count bytes of a 100MB+ file

json - 一个领域模型,多个 json View

c# - 保存添加额外小数位