FabricJS:次分类织物.行和toObject错误

FabricJS: Sub Classing fabric.Line and toObject error

本文关键字:行和 toObject 错误 分类 FabricJS      更新时间:2023-09-26

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

对于带有Lines的toObject方法(Rect和Triangle似乎也有同样的问题),您需要做一些特殊的事情吗?

我的脑袋几乎进水了,所以任何帮助都是非常感激的。

更新1:jsfiddle添加

下面是一个基本示例的jsfiddle。你可以在第124125行看到,我添加了一个引用到一行,末尾和箭头连接到:

arrow.line = line;
end.line = line;

当您尝试序列化(检查控制台)时,正是这个引用抛出了错误:

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

正如我在上面的注释中所写的,您的序列化失败是因为行组件、端组件和箭头组件相互之间有循环引用,所以当您序列化行时,请序列化序列化行的端,序列化端,依此类推,直到您陷入堆栈溢出异常。

我建议你改变你的设计,改为使用一个组,并将你的线条、末端和箭头添加到组中;扩展组应该是最好的选择,你可以把它想象成一个单独的组件,其中有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中管理循环引用的唯一解决方案是Douglas Crockford的Cycle.js,但要使用它,您应该修改FabricJS的.toJSON()方法。

我的意见是使用属性ID和FindById方法,或者使用字符串属性来字符串化引用,但如果可以的话,尽量避免循环引用。