【问题标题】:FabricJS: Sub Classing fabric.Line and toObject errorFabricJS:子类 fabric.Line 和 toObject 错误
【发布时间】:2014-09-06 06:06:35
【问题描述】:

我过去曾使用 fabricjs 成功地对组进行子类化,但是在尝试对 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。您可以在第 124、125 行看到我添加了对附加了端点和箭头的行的引用:

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

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

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

【问题讨论】:

  • +1 尝试添加一个JSFiddle的例子
  • @wintermute 我刚刚添加了,看上面的编辑
  • 你的序列化代码陷入无限递归,这条语句end.line = line;是负责任的,end.line点对线,而line.end点对端
  • 啊,我明白@wintermute 你的意思了,那么如何保留对端点所属行的引用(然后是行的端点),还是应该在其他地方保存该引用?不过,它确实给了我一个新的思路,谢谢。请记住将您的答案添加为答案而不是评论,以便如果它是解决方案,我可以投票。

标签: javascript fabricjs


【解决方案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 方法,或者使用字符串属性来对引用进行字符串化,但尽量避免循环引用。

【讨论】:

  • 感谢您的建议,在这种情况下,由于需要“抓住”行的每一端以更改其旋转等,因此组不起作用。(演示没有显示,我的错)。话虽如此,您的回答为我指明了正确的方向,当我解决问题时,我一定会更新解决方案。
猜你喜欢
  • 1970-01-01
  • 2020-02-25
  • 2018-06-26
  • 2016-01-29
  • 2012-11-09
  • 2015-07-10
  • 2017-02-25
  • 1970-01-01
  • 2015-06-22
相关资源
最近更新 更多