Fabric.js现有Shape fromObject Error

时间:2017-09-18 14:14:40

标签: javascript subclass fabricjs

在我继续尝试在Fabric.js中创建可以保存和加载的自定义类的传奇。我正在尝试扩展Line和Circle类并添加一些自定义属性......但是在尝试加载数据时我遇到了问题。它保存好了,我的简单'name'属性就在那里,但是在尝试加载时,我陷入了“enlivenObjects”函数,即klass从fabric.util.getKlass函数中获取该对象类型。对于我的对象我没有得到任何回报(“未定义”)。 在附带的示例中,如果单击“SAVE”将画布的数据放入DIV,则可以“清除”画布并尝试“加载”数据。尝试加载时发生错误。 因此,在JS控制台窗口中,我可以运行“fabric.util.getKlass('Line')”并且可以工作,我得到一个对象,但当我对'namedCircle'或'namedLine'执行相同操作时,我得到了未定义... 有什么想法吗?这种方法对我不起作用吗?

var canvas;
            
    window.onload = function() {
        canvas = new fabric.Canvas('c');

        /**
         * Attempt to make a custom Line, inherited from the fabric.Line
         * currently has a custom attribute of 'name'
         * 
         */
        fabric.namedLine = fabric.util.createClass(fabric.Line, {
            type: 'namedLine',
            initialize: function(points, options) {
                options || (options = { });
                this.callSuper('initialize', points, options);
                this.set('name', options.name || '');
            },
            toObject: function() {
                return fabric.util.object.extend(this.callSuper('toObject'), {
                name: this.get('name')
                });
            },
            fromObject: function(object, callback) {
                return fabric.Object._fromObject('namedLine', options, callback);
            },
            _render: function(ctx) {
                this.callSuper('_render', ctx);
            }
        });

        /**
         * Attempt at custom Circle, inherited from fabric.Circle with
         * a 'name' attribute.
         * 
         */
        fabric.namedCircle = fabric.util.createClass(fabric.Circle, {
            type: 'namedCircle',
            initialize: function(options) {
                options || (options = { });
                this.callSuper('initialize', options);
                this.set('name', options.name || '');
            },
            toObject: function() {
                return fabric.util.object.extend(this.callSuper('toObject'), {
                name: this.get('name')
                });
            },
            fromObject: function(object, callback) {
                return fabric.Object._fromObject('namedCircle', object, callback);
            },
            _render: function(ctx) {
                this.callSuper('_render', ctx);
            }
        });
        
        fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';

        // First Create our line.
        var line = makeLine([ 250, 125, 250, 175 ], "myLine");
        canvas.add(line);
        
        // Now we create our circles, linking to our line.
        canvas.add(
            // first circle is at top of line, line1 is null, line2 is the line.
            makeCircle(line.get('x1'), line.get('y1'), "head", null, line),

            // second circle is at the bottom, line 1 is the line, nothing for line 2.
            makeCircle(line.get('x2'), line.get('y2'), "tail", line),
        );

        canvas.on('object:moving', function(e) {
            var p = e.target;
            // set bottom of the line to the shapes left and top position.
            p.line1 && p.line1.set({ 'x2': p.left, 'y2': p.top });
            // set the top to the line to the circle position.
            p.line2 && p.line2.set({ 'x1': p.left, 'y1': p.top });
            canvas.renderAll();
        });

        // Add our button events.
        document.getElementById("btnSave").addEventListener("click", saveData);
        document.getElementById("btnLoad").addEventListener("click", loadData);
        document.getElementById("btnClear").addEventListener("click", clearData);

    };

    // our circle has up to 2 links.
    function makeCircle(left, top, name, line1, line2) {
        var c = new fabric.namedCircle({
            left: left,
            top: top,
            strokeWidth: 5,
            radius: 12,
            fill: '#fff',
            stroke: '#666',
            name: name
        });
        c.hasControls = c.hasBorders = false;

        c.line1 = line1;
        c.line2 = line2;

        return c;
    }

    function makeLine(coords, name) {
        return new fabric.namedLine(coords, {
            fill: 'red',
            stroke: 'red',
            strokeWidth: 5,
            selectable: false,
            name: name
        });
    }

    function saveData() {
        document.getElementById("out").innerHTML = "";
        document.getElementById("out").innerHTML = JSON.stringify(canvas.toDatalessJSON());
    };

    function loadData() {
        var data = document.getElementById("out").innerHTML;
        console.log(data);
        canvas.loadFromDatalessJSON(data);
        canvas.renderAll();
    };

    function clearData() {
        canvas.clear();
    }
#out {
    width:500px;
    height:300px;
    border:1px solid red;
    overflow:scroll;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.19/fabric.min.js"></script>
<canvas style="border: 2px solid; " height="500" width="600" id="c"></canvas>
<p>
  <button id="btnSave">Save</button>
  <button id="btnClear">Clear</button>
  <button id="btnLoad">Load</button>
</p>
<div id="out"></div>

1 个答案:

答案 0 :(得分:1)

嗯,有时你只需要远离事物并思考它。 我仔细研究了getKlass函数,并将类名称的第一个字符大写......所以修复是将类从“namedLine”和“namedCircle”更改为“NamedLine”和“NamedCircle”。 我要做的另一件事是将返回函数移到类之外。

    var canvas;
            
    /**
     * Attempt to make a custom Line, inherited from the fabric.Line
     * currently has a custom attribute of 'name'
     * 
     */
        fabric.NamedLine = fabric.util.createClass(fabric.Line, {
        type: 'NamedLine',
        initialize: function(points, options) {
            options || (options = { });
            this.callSuper('initialize', points, options);
            this.set('name', options.name || '');
        },
        toObject: function() {
            return fabric.util.object.extend(this.callSuper('toObject'), {
            name: this.get('name')
            });
        },
        _render: function(ctx) {
            this.callSuper('_render', ctx);
        }
    });
    fabric.NamedLine.fromObject = function(object, callback) {
        callback && callback(new fabric.NamedLine([object.x1, object.y1, object.x2, object.y2], object));
    };


    /**
     * Attempt at custom Circle, inherited from fabric.Circle with
     * a 'name' attribute.
     * 
     */
    fabric.NamedCircle = fabric.util.createClass(fabric.Circle, {
        type: 'NamedCircle',
        initialize: function(options) {
            options || (options = { });
            this.callSuper('initialize', options);
            this.set('name', options.name || '');
        },
        toObject: function() {
            return fabric.util.object.extend(this.callSuper('toObject'), {
            name: this.get('name')
            });
        },
        _render: function(ctx) {
            this.callSuper('_render', ctx);
        }
    });

    fabric.NamedCircle.fromObject = function(object, callback) {
        return fabric.Object._fromObject('NamedCircle', object, callback);
    };

    fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';




    window.onload = function() {
        canvas = new fabric.Canvas('c');

        
        // First Create our line.
        var line = makeLine([ 250, 125, 250, 175 ], "myLine");
        canvas.add(line);
        
        // Now we create our circles, linking to our line.
        canvas.add(
            // first circle is at top of line, line1 is null, line2 is the line.
            makeCircle(line.get('x1'), line.get('y1'), "head", null, line),

            // second circle is at the bottom, line 1 is the line, nothing for line 2.
            makeCircle(line.get('x2'), line.get('y2'), "tail", line),
        );

        canvas.on('object:moving', function(e) {
            var p = e.target;
            // set bottom of the line to the shapes left and top position.
            p.line1 && p.line1.set({ 'x2': p.left, 'y2': p.top });
            // set the top to the line to the circle position.
            p.line2 && p.line2.set({ 'x1': p.left, 'y1': p.top });
            canvas.renderAll();
        });

        // Add our button events.
        document.getElementById("btnSave").addEventListener("click", saveData);
        document.getElementById("btnLoad").addEventListener("click", loadData);
        document.getElementById("btnClear").addEventListener("click", clearData);

    };

    // our circle has up to 2 links.
    function makeCircle(left, top, name, line1, line2) {
        var c = new fabric.NamedCircle({
            left: left,
            top: top,
            strokeWidth: 5,
            radius: 12,
            fill: '#fff',
            stroke: '#666',
            name: name
        });
        c.hasControls = c.hasBorders = false;

        c.line1 = line1;
        c.line2 = line2;

        return c;
    }

    function makeLine(coords, name) {
        return new fabric.NamedLine(coords, {
            fill: 'red',
            stroke: 'red',
            strokeWidth: 5,
            selectable: false,
            name: name
        });
    }

    function saveData() {
        document.getElementById("out").innerHTML = "";
        document.getElementById("out").innerHTML = JSON.stringify(canvas.toDatalessJSON());
    };

    function loadData() {
        var data = document.getElementById("out").innerHTML;
        console.log(data);
        canvas.loadFromDatalessJSON(data);
        canvas.renderAll();
    };

    function clearData() {
        canvas.clear();
    }
#out {
    width:500px;
    height:300px;
    border:1px solid red;
    overflow:scroll;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.19/fabric.min.js"></script>
<canvas style="border: 2px solid; " height="500" width="600" id="c"></canvas>
<p>
  <button id="btnSave">Save</button>
  <button id="btnClear">Clear</button>
  <button id="btnLoad">Load</button>
</p>
<div id="out"></div>