You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从JSON重新加载基于fabric.Polyline的自定义FabricJS Canvas对象?

Fixing loadFromJSON Error with Custom FabricJS Polyline Class

Let's break down why you're hitting that Cannot read property 'x' of undefined error and fix it step by step.

Root Cause

The issue lies in how your fabric.TreeNode class initializes its parent fabric.Polyline class.

fabric.Polyline's constructor expects two arguments: first the array of points, then an options object. Your current initialize method only accepts an options parameter and passes that to the parent constructor—this means the polyline's points never get properly initialized under the hood. When you serialize and deserialize, Fabric tries to process invalid points data, leading to the TypeError.

Corrected Code

Here's the fixed version of your custom class and related code:

var canvas = new fabric.Canvas('c', { });

// Fixed custom TreeNode class
fabric.TreeNode = fabric.util.createClass(fabric.Polyline, {
    type: 'treeNode',
    // Initialize now accepts points + options, matching Polyline's signature
    initialize: function (points, options) {
        options || (options = {});
        // Pass points first, then options to the parent constructor
        this.callSuper('initialize', points, options);
        // Use Fabric's set() method for consistent property handling
        this.set('stroke', 'blue');
    },
    toObject: function () {
        // Extend parent's toObject output with our custom properties
        return fabric.util.object.extend(this.callSuper('toObject'), {
            stroke: this.get('stroke')
        });
    },
    _render: function (ctx) {
        this.callSuper('_render', ctx);
    }
});

// Fix fromObject to leverage Polyline's point-handling logic
fabric.TreeNode.fromObject = function (object, callback) {
    // Use Polyline's fromObject method, specifying our custom class name
    return fabric.Polyline.fromObject(object, callback, 'TreeNode');
};

// Rest of your code remains the same
var rect = new fabric.Rect({
    left: 300,
    top: 200,
    fill: 'blue',
    width: 50,
    height: 50,
});
canvas.add(rect);

var node = new fabric.TreeNode([{ x: 50, y: 100 }, { x: 200, y: 300 }, { x: 10, y: 10 }]);
canvas.add(node);

var myJSON = JSON.stringify(canvas);
canvas.loadFromJSON(myJSON, canvas.renderAll.bind(canvas));

Key Fixes Explained

  1. Adjusted initialize Signature:

    • Changed to accept points as the first parameter, followed by options, matching fabric.Polyline's constructor.
    • Passed both points and options to callSuper so the parent class correctly initializes the polyline's shape data.
  2. Fixed fromObject Method:

    • Instead of using fabric.Object._fromObject, we use fabric.Polyline.fromObject which already handles the parsing of polyline points. The third argument tells it to instantiate our custom TreeNode class instead of a standard Polyline.
  3. Used Fabric's set() Method:

    • Replaced direct property assignment (this.stroke = 'blue') with this.set('stroke', 'blue') to ensure Fabric tracks the property correctly for serialization/deserialization.

With these changes, your custom TreeNode class will serialize and deserialize properly using canvas.loadFromJSON() without throwing errors.

内容的提问来源于stack exchange,提问作者Emile Haas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 10:38:11