63

現在のキャンバスの状態をおそらく 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メソッドを使用して、キャンバスに追加する生地オブジェクトにいくつかのカスタム属性も設定しています。

// 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();

問題は、サーバー側でリクエストを確認すると、カスタム属性がキャンバスから解析されず、他のすべてのものと一緒に送信されていることがわかります。これはおそらく、toObjectメソッドがオブジェクト クラスのデフォルト属性ではないものを削除する方法に関係しています。サーバーから送信された JSON 文字列からキャンバスを保存および復元でき、復元されたキャンバスにもカスタム属性が含まれるように、この問題に取り組む良い方法は何でしょうか? ありがとう。

4

5 に答える 5

79

良い質問。

オブジェクトにカスタム プロパティを追加する場合、それらのオブジェクトは何らかの形で「特別」である可能性があります。それらをサブクラス化することが合理的な解決策になるようです。

たとえば、fabric.Imagea を名前付きイメージにサブクラス化する方法を次に示します。これらの画像オブジェクトは、"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して、返されたオブジェクトに「name」を含めます (これは、ファブリックでのオブジェクトのシリアル化の基礎です)。

最後に、fabric.NamedImage.fromObject前述したことも実装する必要があります。これにより、 loadFromJSONJSON 解析中にどのメソッドを呼び出すかがわかるようになります。

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

ここで ("object.src" から) 画像を読み込み、そこから のインスタンスを作成しますfabric.NamedImage。以前に「initialize」メソッドを上書きしたため、その時点でコンストラクターが「name」設定を処理することに注意してください。

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);
});
于 2012-06-30T17:28:18.233 に答える
2

より簡単な方法は、文字列化後にプロパティを追加することです。

var stringJson = JSON.stringify(this.canvas);
var objectJson = JSON.parse(string.Json);

//remove property1 property
delete objectJson.property1;

//add property2 property
delete objectJson.property2;

// stringify the object again
stringJson = JSON.stringify(objectJson);

// at this point stringJson is ready to be sent over to the server
$http.post('http://serverurl/',stringJson);
于 2014-09-17T14:51:25.627 に答える