FabricJS:Sub Classing fabric.Line和toObject错误

时间:2014-09-04 08:55:28

标签: javascript fabricjs

我过去曾使用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;

当您尝试序列化(检查控制台)时,此引用会引发错误:

http://jsfiddle.net/iamadamjowett/zL5k0zx3/29/

1 个答案:

答案 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方法,或使用字符串属性,您将对引用进行字符串化,但如果可以,请尝试避免循环引用。