从json加载stickman不会持久化线坐标旋转逻辑

时间:2015-06-26 17:09:48

标签: canvas fabricjs

加载stickman.tojson后,圆圈和直线旋转逻辑消失了。

我能够复制stickman逻辑以向对象添加线条,并且当​​我移动线条时线条将旋转并跟随对象。我使用canvas.toJSON来保存Json,所有这一切都很好。我可以使用canvas.loadFromJSON(json)加载Json并加载它。

问题是我加载后,当我移动圆圈时,线条不跟随并旋转。我尝试搜索要包含在toJSON()中的属性,但我找不到任何内容。

http://fabricjs.com/stickman/

这是一个jsfiddle样本。

    var canvas = this.__canvas = new fabric.Canvas('c', { selection: false });
  fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';

saveNow = (function(){
    var jsonSave = JSON.stringify(canvas.toJSON())
   // alert(jsonSave);
    sessionStorage.canvase = jsonSave;     
});

loadNow = (function(){
    var jsonLoad = sessionStorage.canvase;
   // alert(jsonLoad);
    canvas.loadFromJSON(jsonLoad, canvas.renderAll.bind(canvas));
});

(function() {


  function makeCircle(left, top, line1, line2, line3, line4) {
    var c = new fabric.Circle({
      left: left,
      top: top,
      strokeWidth: 5,
      radius: 12,
      fill: '#fff',
      stroke: '#666'
    });
    c.hasControls = c.hasBorders = false;

    c.line1 = line1;
    c.line2 = line2;
    c.line3 = line3;
    c.line4 = line4;

    return c;
     }

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

  var line = makeLine([ 250, 125, 250, 175 ]),
      line2 = makeLine([ 250, 175, 250, 250 ]),
      line3 = makeLine([ 250, 250, 300, 350]),
      line4 = makeLine([ 250, 250, 200, 350]),
      line5 = makeLine([ 250, 175, 175, 225 ]),
      line6 = makeLine([ 250, 175, 325, 225 ]);

  canvas.add(line, line2, line3, line4, line5, line6);

  canvas.add(
    makeCircle(line.get('x1'), line.get('y1'), null, line),
    makeCircle(line.get('x2'), line.get('y2'), line, line2, line5, line6),
    makeCircle(line2.get('x2'), line2.get('y2'), line2, line3, line4),
    makeCircle(line3.get('x2'), line3.get('y2'), line3),
    makeCircle(line4.get('x2'), line4.get('y2'), line4),
    makeCircle(line5.get('x2'), line5.get('y2'), line5),
    makeCircle(line6.get('x2'), line6.get('y2'), line6)
  );

  canvas.on('object:moving', function(e) {
    var p = e.target;
    p.line1 && p.line1.set({ 'x2': p.left, 'y2': p.top });
    p.line2 && p.line2.set({ 'x1': p.left, 'y1': p.top });
    p.line3 && p.line3.set({ 'x1': p.left, 'y1': p.top });
    p.line4 && p.line4.set({ 'x1': p.left, 'y1': p.top });
    canvas.renderAll();
  });
})();

http://jsfiddle.net/pec86/28/

重现的步骤: 1.移动圆形物体。 2.单击“保存”按钮。 3.移动圆形物体。 4.单击“加载”按钮。 5.移动圆形物体。现在,这将揭示我想要修复/坚持的内容。

提前致谢。

1 个答案:

答案 0 :(得分:2)

您遇到的问题是canvas.toJSON()会保存所有结构的对象,如画布中所示,但不会保存您自己的对象,因此会松动参考文献,例如圆圈和线条之间的链接。

我不是fabric.js专家所以可能有一个更简单的解决方案,但是我重写了你的代码,以便它可以完成你想要做的事情。
我使用数组来存储我们所有的行,现在saveNow()函数只保存这些行的坐标。 我还必须重写绘图函数,现在放入init()函数。

另外,请注意它有点脏:

var canvas = this.__canvas = new fabric.Canvas('c', {
    selection: false
});
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';

(function () {
    //Some other objects
    canvas.add(
        new fabric.Rect({ top: 100, left: 100, width: 50, height: 50, fill: '#f55' }),
        new fabric.Circle({ top: 140, left: 230, radius: 75, fill: 'green' }),
        new fabric.Triangle({ top: 300, left: 210, width: 100, height: 100, fill: 'blue' })
      );
    var lines,
    links = [[0,1,4,5], [1,2,3], [2], [3], [4], [5]];

    var saveNow = function () {
        //save our stickMan
        var coords = [],l;
        for (var i = 0; l = lines[i]; i++) {
            coords.push([l.x1, l.y1, l.x2, l.y2]);
        }
        sessionStorage.stickman = JSON.stringify(coords);
        //Hide our stickman
        lines.forEach(function(l){canvas.remove(l)});
        circles.forEach(function(c){canvas.remove(c)});
        //save the rest of the canvas
        sessionStorage.canvase = JSON.stringify(canvas.toJSON());
        //unhide stickman
        lines.forEach(function(l){canvas.add(l)});
        circles.forEach(function(c){canvas.add(c)});
        canvas.renderAll();
    };

    var loadNow = function () {
        var coords = JSON.parse(sessionStorage.stickman);
        canvas.clear();
        var jsonLoad = sessionStorage.canvase;
        canvas.loadFromJSON(jsonLoad, function(){canvas.renderAll.bind(canvas); init(coords);});
    };
    var btns = document.querySelectorAll('button');
    btns[0].addEventListener('click', saveNow, false);
    btns[1].addEventListener('click', loadNow, false);
    var circles;
    function makeCircle(left, top, l) {
        var c = new fabric.Circle({
            left: left,
            top: top,
            strokeWidth: 5,
            radius: 12,
            fill: '#fff',
            stroke: '#666'
        });
        c.hasControls = c.hasBorders = false;
        for (var i = 0; i < links.length; i++) {
            c["line" + i] = lines[l[i]];
        }
        circles.push(c);
        return c;
    }

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

    function init(coords) {
        coords = coords || [
            [250, 125, 250, 175],
            [250, 175, 250, 250],
            [250, 250, 300, 350],
            [250, 250, 200, 350],
            [250, 175, 175, 225],
            [250, 175, 325, 225]
        ];
        lines = circles = [];
        var i;
        for (i = 0; i < coords.length; i++) {
            lines.push(makeLine(coords[i]));
        }
        for (i = 0; i < lines.length; i++) {
            canvas.add(lines[i]);
        }
        for (i = 0; i < lines.length; i++) {
            if (i === 0) {
                canvas.add(makeCircle(lines[i].get('x1'), lines[i].get('y1'), [null, 0]));
                canvas.add(makeCircle(lines[i].get('x2'), lines[i].get('y2'), links[i]));
            } else canvas.add(makeCircle(lines[i].get('x2'), lines[i].get('y2'), links[i]));
        }
    }
    canvas.on('object:moving', function (e) {
        var p = e.target;
        p.line0 && p.line0.set({'x2': p.left,'y2': p.top});
        p.line1 && p.line1.set({'x1': p.left,'y1': p.top});
        p.line2 && p.line2.set({'x1': p.left,'y1': p.top});
        p.line3 && p.line3.set({'x1': p.left,'y1': p.top});
        canvas.renderAll();
    });

    init();
})();

▶︎ JsFiddle

替代将按照this answer中的建议对您的对象进行子类化。