1

I have a rect A with the custom property "childs", this property is an array to which I put rects B. The rect B has a custom property "another".

The problem is that after serializing the canvas and loading the json on the canvas, the event listener does not load the property "another" of the rect B.

Here you can see the problem better: https://jsfiddle.net/ps7566/y3k5b4c1/

var a = new fabric.Rect({
   left: 70,
   top: 70,
   fill: 'blue',
   width: 100,
   height: 100
});
var b = new fabric.Rect({
   left: 75,
   top: 75,
   fill: 'red',
   width: 50,
   height: 50
});
b.another = 'property';//this custom property is losed in event observer after serialize
a.childs = [];
a.childs.push(b);
canvas.add(a);

canvas.observe("mouse:up",function(e){
if(e.target != null){
   console.log(e.target);
   alert(e.target.childs[0].another);
   //why this is undefined after serialize and load json? 
}
});
function serialize(){
    json = JSON.stringify(canvas.toJSON(['childs','another']));
}
function loadJSON(){
    canvas.loadFromJSON(json);
}

I want that the event listener can access the property "another" even after loading a JSON.

Lucas Hendren
  • 2,786
  • 2
  • 18
  • 33
  • 2
    Possible duplicate of [Fabric.js - how to save canvas on server with custom attributes](https://stackoverflow.com/questions/11272772/fabric-js-how-to-save-canvas-on-server-with-custom-attributes) – JasonB Jul 08 '19 at 03:37
  • I think it's different, because with canvas.item(1).another I can access that property. but not with an eventlistener that is what I need strictly. also I cant access the functions of object B that inherit from fabricjs like set() or toSVG() – Pablo Sanchez Jul 08 '19 at 07:12

1 Answers1

2

The problem is that after you load the json the childs objects are not klass objects. You need to rewritethe toObject and fromObject methods. In fromObject method you need to put forceAsync to false since you need to wait for childs to be created.

var canvas = new fabric.Canvas("c",{
 width: 600,
  height: 500,
  backgroundColor: 'cyan'
});
var a = new fabric.Rect({
  left: 70,
  top: 70,
  fill: 'blue',
  width: 100,
  height: 100
});
var b = new fabric.Rect({
  left: 75,
  top: 75,
  fill: 'red',
  width: 50,
  height: 50
});
b.another = 'property';//this custom property is losed in event observer after serialize;
a.another = 'property';//this custom property is losed in event observer after serialize;
a.childs = [];
a.childs.push(b);
a.childs.push(b);
canvas.add(a);
//function printObj(){
// console.log(r);
//}
//function addChild(){
// r.childs.push(s);
//}
var json;
 serialize = function(){
 json = JSON.stringify(canvas.toJSON(['childs','another']));
}
  loadJSON = function(){
  
  canvas.clear();

 canvas.loadFromJSON(json);
}
canvas.observe("mouse:up",function(e){
 if(e.target != null){
   console.log(e.target);
    alert(e.target.childs[0].another);//why this is undefined after serialize and load json? 
  }
});
fabric.Rect.prototype.toObject = (function(toObject) {
    return function(propertiesToInclude) {
        var data = toObject.call(this,propertiesToInclude),childs=[];
        
        if(this.childs && this.childs.length){
          for(var i= 0 ; i<this.childs.length; i++){
             childs.push(this.childs[i].toObject(propertiesToInclude));
           }
           
        }
        data.childs = childs;
        return data;
    };
})(fabric.Rect.prototype.toObject);
fabric.Rect.fromObject = function(object, callback, forceAsync) {
 
    var obj = fabric.Object._fromObject('Rect', object, null, false);
    obj.childs = [];
    if(object.childs && object.childs.length){
      for(var i= 0 ; i<object.childs.length; i++){
           obj.childs[i] = fabric.Object._fromObject('Rect', object.childs[i], null, 0);
       }
    }
    return callback ? callback(obj) : obj;
  };


//The project has to be programmed in this way. with an array, event o
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.20/fabric.js"></script>
<!-- <button onClick="printObj()">Print rect</button> -->
<!-- <button onClick="addChild()">Add Child</button> -->
<button onClick="serialize()">Serialize</button>
<button onClick="loadJSON()">Load JSON</button>
<!-- <button onClick="canvas.remove(r)">Delete Rect</button>  -->
<canvas id="c"></canvas>
Marius Turcu
  • 1,511
  • 7
  • 14
  • Your solution doesnt load the json well. You can see it moving the object before loading the json – Pablo Sanchez Jul 08 '19 at 18:19
  • @PabloSanchez on my side it seems to work..can you please provide more details? – Marius Turcu Jul 09 '19 at 08:03
  • I don't know if it's because that's the way it should work but it looks like it doesn't load the JSON. Is not the first button necessary in this solution? I mean, the second button also serialize? if I click the first button, then I move the object and then I click the second button, it seems that the second did not work – Pablo Sanchez Jul 09 '19 at 12:49
  • 1
    That part is from your code man, one button serialize the canvas and the other one will load the json saved when you press the serialize button. In conclusion if you change something in the canvas between those 2 presses you will lose the changes. I just implement the stuff regarding custom property on canvas – Marius Turcu Jul 09 '19 at 13:00