【问题标题】:Fabric.js New Class from existing Shape fromObject ErrorFabric.js 来自现有形状的新类 fromObject 错误
【发布时间】:2017-09-19 01:26:57
【问题描述】:

在我尝试在 Fabric.js 中创建一个可以保存和加载的自定义类的持续传奇中。我正在尝试扩展 Line 和 Circle 类并添加一些自定义属性...但是在尝试加载数据时遇到了问题。它保存好,我的简单“名称”属性在那里,但是当尝试加载时,我卡在“enlivenObjects”函数中,即 klass 从 fabric.util.getKlass 函数获取该对象类型的地方。我的对象没有得到任何回报(“未定义”)。 在附加的示例中,如果您单击“保存”,则画布的数据被放入 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>

【问题讨论】:

    标签: javascript subclass fabricjs


    【解决方案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>

    【讨论】:

      猜你喜欢
      • 2019-03-29
      • 2013-12-15
      • 2012-05-14
      • 1970-01-01
      • 2021-11-24
      • 1970-01-01
      • 1970-01-01
      • 2020-06-12
      • 1970-01-01
      相关资源
      最近更新 更多