我过去曾使用fabricjs成功地对Groups进行了子类化,但是在尝试子类化Line对象时,我遇到了toObject()
方法的各种问题。
目前我的代码如下:
fabric.ConnectorLine = fabric.util.createClass(fabric.Line, {
initialize: function (points, options) {
options || (options = {});
this.callSuper('initialize', points, options);
options &&
this.set('type', 'connector') &&
this.set('end1', options.end1) &&
this.set('arrow', options.arrow)
},
toObject: function () {
return fabric.util.object.extend(this.callSuper('toObject'), {
type: this.type,
end1: this.end1,
arrow: this.arrow
});
}
});
fabric.ConnectorLine.fromObject = function (object, callback) {
var _enlivenedObjects;
fabric.util.enlivenObjects(object.objects, function (enlivenedObjects) {
delete object.objects;
_enlivenedObjects = enlivenedObjects;
});
return new fabric.ConnectorLine(_enlivenedObjects, object);
};
当我尝试序列化此对象时,收到以下错误消息:
RangeError: Maximum call stack size exceeded
at klass.callSuper (fabric.js:1475:30)
at klass.fabric.Line.fabric.util.createClass.toObject (fabric.js:13632:26)
使用带有行的toObject
方法是否需要特殊处理(Rect和Triangle似乎也有相同的问题)?
刚刚完成了我的工作,所以任何帮助都是最受欢迎的。
更新1:jsfiddle添加
这是一个基本示例的jsfiddle。您可以在第124,125行看到我添加了对结束和箭头所附加的行的引用:
arrow.line = line;
end.line = line;
当您尝试序列化(检查控制台)时,此引用会引发错误:
答案 0 :(得分:1)
正如我在上面的注释中所写的那样,序列化失败是因为行组件,结束组件和箭头组件彼此具有循环引用,因此当序列化行时,序列化序列化行的末尾,序列化结束等等,直到陷入堆栈溢出异常。
我建议你改变你的设计,改用一个组,然后将你的线,结束和箭头添加到组中;扩展组应该是最好的选择,你可以把它想象成一个没有严格引用的3个子组件的单个组件。
我尝试了一个丑陋而肮脏的解决方案,但没有我想要的东西:
fabric.ConnectorEnd = fabric.util.createClass(fabric.Rect, {
initialize: function (options) {
options || (options = {});
this.callSuper('initialize', options);
recursionCount = 0;
options &&
this.set('type', 'connector-end') &&
this.set('line', options.line) &&
this.set('attachedTo', options.attachedTo) &&
this.set('attachedPos', options.attachedPos)
},
toObject: function () {
if (recursionCount > 100) return; // added a recursion limit
recursionCount++;
return fabric.util.object.extend(this.callSuper('toObject'), {
type: this.type,
line: this.line,
attachedTo: this.attachedTo,
attachedPos: this.attachedPos
});
}
});
无效......
fabric.ConnectorEnd = fabric.util.createClass(fabric.Rect, {
initialize: function (options) {
options || (options = {});
this.callSuper('initialize', options);
options &&
this.set('type', 'connector-end') &&
this.set('line', options.line) &&
this.set('attachedTo', options.attachedTo) &&
this.set('attachedPos', options.attachedPos) &&
this.set('recursions', 0)
},
toObject: function () {
if (this.line.recursions > 0 && this.recursions > 1) { return; }
return fabric.util.object.extend(this.callSuper('toObject'), {
recursions: this.recursions++,
type: this.type,
line: this.line,
attachedTo: this.attachedTo,
attachedPos: this.attachedPos
});
}
});
行不通......可怕无用......我怎么建议你使用这种糟糕的代码?我能做什么?是的,我发现在JSON中管理循环引用的唯一解决方案是Cycle.js of Douglas Crockford,但要使用它,您应该修改FabricJS的.toJSON()
方法。
我的意见是使用属性ID和FindById方法,或使用字符串属性,您将对引用进行字符串化,但如果可以,请尝试避免循环引用。