Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
489 views
in Technique[技术] by (71.8m points)

javascript - Fabric.js subclassing fabric.Group - Error: "Cannot read property 'async' of undefined" when load from JSON

Have the following issue:

Trying to subclass fabric.Group:

var CustomGroup = fabric.util.createClass(fabric.Group, {
    type : 'customGroup',

    initialize : function(objects, options) {
        options || ( options = { });

        this.callSuper('initialize', objects, options);
        this.set('customAttribute', options.customAttribute || 'undefinedCustomAttribute');
    },

    toObject : function() {
        return fabric.util.object.extend(this.callSuper('toObject'), {
            customAttribute : this.get('customAttribute')
        });
    },

    _render : function(ctx) {
        this.callSuper('_render', ctx);
    }
});

Testcase:

I create a red rectangle and added it to the custom group:

function drawTestRect() {
    // create a rectangle object
    var rect = new fabric.Rect({
        left : 100,
        top : 100,
        fill : 'red',
        width : 20,
        height : 20
    });

    var cgroup = new CustomGroup([rect], {
        top : 50,
        left : 50,
        customAttribute : 'Hello World'
    });

    canvas.add(cgroup);

};

Problem: I want to get JSON of the canvas and afterwards I want to load canvas from JSON.

drawTestRect()

var savedCanvas = canvas.toJSON();

canvas.clear();

canvas.loadFromJSON(savedCanvas);

Everything is working fine (Rect/Group is drawn; JSON is valid), but when I load from JSON, I get the following error in the console:

TypeError: Cannot read property 'async' of undefined

What I've tried yet:

  • I added "CustomGroup.async = false;". But didn't help
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The error "Cannot read property 'async' of undefined" is raised because no "klass" can be found - https://github.com/kangax/fabric.js/blob/master/src/util/misc.js#L214-215.

You have to assign your custom object to fabric object - otherwise canvas.loadFromJSON() doesn't work.

var fabric.CustomGroup = fabric.util.createClass(fabric.Group, {
    type : 'customGroup',

    initialize : function(objects, options) {
        options || ( options = { });

        this.callSuper('initialize', objects, options);
        this.set('customAttribute', options.customAttribute || 'undefinedCustomAttribute');
    },

    toObject : function() {
        return fabric.util.object.extend(this.callSuper('toObject'), {
            customAttribute : this.get('customAttribute')
        });
    },

    _render : function(ctx) {
        this.callSuper('_render', ctx);
    }
});

Additionally you have to declare the fromObject method - it's needed for loadFromJSON. In this case your object is load synchronous.

fabric.CustomGroup.fromObject = function (object, callback) {
    var _enlivenedObjects;
    fabric.util.enlivenObjects(object.objects, function (enlivenedObjects) {
        delete object.objects;
        _enlivenedObjects = enlivenedObjects;
    });
    return new fabric.CustomGroup(_enlivenedObjects, object);
};

If your custom object is loaded async you have to do this:

fabric.CustomGroup.fromObject = function (object, callback) {
    fabric.util.enlivenObjects(object.objects, function (enlivenedObjects) {
        delete object.objects;
        callback && callback(new fabric.CustomGroup(enlivenedObjects, object));
    });
};

fabric.CustomGroup.async = true;

I've made a small jsfiddle testcase: http://jsfiddle.net/Kienz/qPLY6/


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...