Reputation: 2747
I am using fabricJS version 1.7.22. I want to implement functionality of grouping and UnGrouping.
When I convert my canvas into json using toJSON(list_of_custom_attribute). my custom attribute not added into json. (custom attribute of subObject which are include in group are not added into json).
Is there any patch for grouping, so that, every time my all custom attribute is add in group's objects.
My grouping code is like below (I borrow this code from fabricJS toGroup() function of latest fabricJS version 2.7.0) :
var activeObject = this.canvas.getActiveGroup();
var objects = activeObject._objects.concat();
activeObject._objects = [];
var options = fabric.Object.prototype.toObject.call(activeObject);
var newGroup = new fabric.Group([]);
delete options.type;
newGroup.set(options);
objects.forEach(function (object) {
if (object) {
object.canvas.remove(object);
object.group = newGroup;
}
});
newGroup._objects = objects;
if (!activeObject.canvas) {
return newGroup;
}
else {
var canvas = activeObject.canvas;
that.extend(newGroup, that.randomId());
canvas.add(newGroup);
canvas._activeObject = newGroup;
newGroup.setCoords();
}
I try some scenario Which may help to understand problem. (my all canvas object must contain custom_attribute called 'id')
1) add one image and clone that image. now convert canvas into json. (JSON contain all my custom attributes like this => [ rect[id], circle[id] ]).
2) add one image and clone that image and group that both image. now convert canvas into json. (JSON contain all my custom attributes like this : => group (rect[id], circle[id]))
3) add one image and clone that image. now convert canvas into json (this is like first scenario). now clear canvas and load that json into canvas again. now make group of that both object. and convert canvas into json it look like this => group( rect[], circle[])
The main problem as after perform loadfromJSON. (scenario 3) after loadfromJSON, my objects of group not contain custom attribute.because my canvas json not contain that attribute.
Upvotes: 5
Views: 1747
Reputation: 11
You can try this code snippet by adding it to your application. It will help you keeping custom_attributes
of objects even after loading from JSON.
fabric.Object.prototype.toObject = (function(toObject) {
//console.log('toObject==>', toObject);
return function(propertiesToInclude) {
return fabric.util.object.extend(toObject.call(this,
propertiesToInclude), {
custom_attribute: this.custom_attribute ?
this.custom_attribute : '',
});
};
})(fabric.Object.prototype.toObject);
Upvotes: 1
Reputation: 15604
To get JSON use selected.toJSON(allCustomAttr) and to clone use object#clone.
var canvas = document.getElementById('c');
var c = new fabric.Canvas(canvas);
c.setHeight(500);
c.setWidth(500);
var allCustomAttr = ['customSourceType', 'id'];
var groupbtn = document.getElementById('group');
var unGroupbtn = document.getElementById('ungroup');
var reload = document.getElementById('reload');
var getJSON = document.getElementById('getJSON');
var selected;
function extend(object, attr) {
//object.set(attr);
object.toObject = (function(toObject) {
return function() {
return fabric.util.object.extend(toObject.call(this), attr);
};
})(object.toObject);
}
c.on({
'object:selected': function(e) {
selected = e.target;
console.log('selected', selected);
console.log('selected', selected.toJSON(allCustomAttr));
}
})
getJSON.addEventListener('click', function() {
console.log('canvas json', c.toJSON(allCustomAttr));
});
reload.addEventListener('click', function() {
var json = c.toJSON(allCustomAttr);
c.clear();
c.loadFromJSON(json, function() {
c.renderAll();
})
});
unGroupbtn.addEventListener('click', function() {
var activeObject = c.getActiveObject();
if (activeObject && activeObject.type != "group") {
return;
}
var items = activeObject.getObjects();
activeObject.destroy();
c.remove(activeObject);
for (var i = 0; i < items.length; i++) {
c.add(items[i]);
}
c.renderAll();
c.loadFromJSON(c.toJSON(allCustomAttr));
});
groupbtn.addEventListener('click', function() {
if (!c.getActiveGroup) {
return;
}
var activegroup = c.getActiveGroup() || c.getActiveObject();
var objectsInGroup = activegroup.getObjects();
var grp = new fabric.Group();
objectsInGroup.forEach((element, index) => {
element.clone((clonedElement) => {
grp.addWithUpdate(clonedElement);
});
});
grp.set({
top: activegroup.top,
left: activegroup.left
})
c.discardActiveGroup();
c.deactivateAllWithDispatch();
objectsInGroup.forEach(function(object) {
c.remove(object);
});
c.add(grp);
c.renderAll();
});
var rect = new fabric.Rect({
height: 100,
width: 100,
top: 100,
left: 100,
fill: 'red'
});
extend(rect, {
"customSourceType": "rect",
"id": 123456
})
c.add(rect);
var text = new fabric.IText('this is text', {
fill: 'green',
top: 150,
left: 220,
fontSize: 30
});
extend(text, {
"customSourceType": "ITEXT",
"id": 987654
})
c.add(text);
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.20/fabric.js"></script>
<button id="reload">
Load from json
</button>
<button id="group">
Group
</button>
<button id="ungroup">
UnGroup
</button>
<button id="getJSON">
GEt json
</button>
<canvas id="c" style="border:1px solid"></canvas>
<ol>
<li>Select both object and group it.</li>
<li> now select that group. and check in console. </li>
<li>please check second log.(there are two log placed on selected event.)</li>
<li>(console) there are objects array in group</li>
<li>expand rect object (first object of array)</li>
<li>try to find custom attributes (customSourceType, id) </li>
<br/>
<li> above step will perfect. </li>
<br/>
<li> Now click on loadFromJson button</li>
<li> now select that group. and check in console. </li>
<li>please check second log.(there are two log placed on selected event.)</li>
<li>(console) there are objects array in group</li>
<li>expand rect object from that array(first object of array)</li>
<li>try to find custom attributes (customSourceType, id) </li>
<li>After loadfromjson there is no custom attributes.</li>
</ol>
Upvotes: 0