Ответ 1
Хороший вопрос.
Если вы добавляете пользовательские свойства к объектам, эти объекты, скорее всего, являются "специальными". Похоже, что подклассификация их будет разумным решением.
Например, здесь мы будем подклассифицировать fabric.Image
на именованное изображение. Эти объекты изображения могли бы иметь такие имена, как "Гэндальф" или "Самопомощь".
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
(constructor), также устанавливаем свойство 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
из него. Обратите внимание, что в этот момент конструктор уже позаботится о настройке "имя", поскольку ранее мы перезаписывали метод "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 "name" is preserved
console.log(canvas.item(0).name);
});