loading stickman from json does not persist line coordinate rotation logic

梦想的初衷 提交于 2019-12-13 05:37:47

问题


After loading stickman.tojson, the circles and line rotation logic is gone.

I was able to duplicate the stickman logic to add lines to objects and the line will rotate and follow the object as I move it. I used canvas.toJSON to save the Json and all of this works fine. I can load the Json with canvas.loadFromJSON(json) and it loads fine.

The issue is after I load it, when I move the circles, the line does not follow and rotate. I tried searching for properties to include in the toJSON() but I was not able to find anything.

http://fabricjs.com/stickman/

Here is a jsfiddle sample.

    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/

Steps to reproduce: 1. Move the circles objects around. 2. Click on the Save button. 3. Move the circles objects around. 4. Click on the Load button. 5. Move the circles objects around. This will now reveal what I am trying to fix/persists.

Thanks in advance.


回答1:


The problem you're facing is that canvas.toJSON() will save all the fabric's objects, as drawn in the canvas but won't save your own objects, and so it will loose the references such as the links between circles and lines.

I am no fabric.js specialist so there might be a simpler solution, however I rewrote your code so that it can accomplish what you tried to do.
I used an array to store all our lines and now the saveNow()function only saves the coordinates of those lines. I also had to rewrite the drawing function, now placed into an init() function.

Also, note that it's kind of dirty :

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

An alternative would be to subclass your objects as proposed in this answer.



来源:https://stackoverflow.com/questions/31078600/loading-stickman-from-json-does-not-persist-line-coordinate-rotation-logic

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!