Stringify only one object in Fabric.js - javascript

I'm working with fabricJS. It's an awesome library for drawing.
var data = JSON.stringify(canvas);
Above command is used to get all the objects along with their properties in JSON format. However, I want to stringfy only an object.
For eg. Creating a rectangle using fabric
var rec = new fabric.Rect({
left: mouse_pos.x,
top: mouse_pos.y,
width: 75,
height: 50,
fill: 'white',
stroke: 'black',
strokeWidth: 3,
padding: 10
});
canvas.add(rec);
I want to get the JSON of only this object(rectangle) being added to the canvas and not the JSON of whole of the canvas being rendered.
May be something like var data = JSON.stringfy(rec);. Is there any way to do so because I want to send the latest object being added to the canvas over sockets and not the whole canvas object which will in turn consumes unnecessary bandwidth because of the JSON object size.

Yes you can! :)
var rect = new fabric.Rect({
left: mouse_pos.x,
top: mouse_pos.y,
width: 75,
height: 50,
fill: 'white',
stroke: 'black',
strokeWidth: 3,
padding: 10
});
canvas.add(rect);
// get last item
var obj = canvas.item(canvas.size() - 1);
// stringify only one object
var json = JSON.stringify(obj);

Can't you just turn your options object into JSON? Then you could send it through sockets, get the JSON on your receiver, parse it and apply into the fabric.Rect function to draw your rect there.
var options = {
left: mouse_pos.x,
top: mouse_pos.y,
width: 75,
height: 50,
fill: 'white',
stroke: 'black',
strokeWidth: 3,
padding: 10
};
var rec = new fabric.Rect(options);
canvas.add(rec);
var yourData = JSON.stringify(options); // turns your options object into JSON
// ...rest of your code, that sends it through sockets...

Related

Fabricjs: cloning a subclassed object makes the clone invisible

I want to make a copy of a fabric object that is a sub-class of a regular fabric class (i.e. a new object with the same properties as the original). Cloning seemed to be the way to go, and indeed cloning a regular object, such as a Rect, works fine. But if I use the same code to clone an instance of a sub-class, the resulting object is not visible on the canvas (although it is listed in the results of canvas.getObjects()).
What am I doing wrong?
Here is a minimal example. This is also at https://codepen.io/micrology/pen/dyKPbRO Running this displays 3 rectangles, two red but only one yellow. There should be 2 yellow rectangles.
var canvas = new fabric.Canvas('canvas')
var rect = new fabric.Rect({
top: 100,
left: 100,
width: 60,
height: 70,
fill: 'red',
})
canvas.add(rect)
var clonedRect
rect.clone((obj) => {
clonedRect = obj
clonedRect.set({left: obj.left + 10, top: obj.top + 10})
})
canvas.add(clonedRect)
var CustomRect = fabric.util.createClass(fabric.Rect, {
type: 'rect',
initialize: function (options) {
this.callSuper('initialize', options)
},
})
var customRect = new CustomRect({
top: 200,
left: 200,
width: 50,
height: 50,
fill: '#ffff00',
})
canvas.add(customRect)
var clonedCustomRect
customRect.clone((obj) => {
clonedCustomRect = obj
clonedCustomRect.set({left: obj.left + 10, top: obj.top + 10})
})
canvas.add(clonedCustomRect)
For people still having this problem, there is currently an open discussion.

unchange the object order

We put the object1 first,then put the object2,and put the object3 finally on the canvas.
It's mean that object1 is on the bottom,and object3 is on the top.
When we want to change the object2 url or do sth on it,we remove it and add the new object2 after.
But now object2 is on the top.
I know some method like sendToBack(),moveTo(),....etc,can change the order of the object2.
There is no clue about fix the object order.
Is there some method already existed or other statement can apply?
If not,is the only way that we change their order again and again by applying method as above after change the object layer?
Thank you.
Use insertAt() to insert the object at given index.
DEMO
var canvas = new fabric.Canvas('c');
var rect1 = new fabric.Rect({
width: 100,
height: 100,
left: 10,
top: 10,
fill: 'red',
});
var rect2 = new fabric.Rect({
width: 100,
height: 100,
left: 30,
top: 30,
fill: 'green',
});
var rect3 = new fabric.Rect({
width: 100,
height: 100,
left: 50,
top: 50,
fill: 'black',
});
var rect4 = new fabric.Rect({
width: 100,
height: 100,
left: 30,
top: 30,
fill: 'yellow',
});
canvas.add(rect1,rect2,rect3);
function alter(){
var index = canvas.getObjects().indexOf(rect2);
//canvas.remove(rect2);
canvas.insertAt(rect4, index,true);
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<button onclick="alter()">Alter</button>
<canvas id="c" width="600" height="600"></canvas>

Fabric.js: Assigning background color to group

I am trying to set a background color for a group without affecting its contained objects.
So far my code looks like this:
var canvas = new fabric.Canvas('canvas');
var helloText = new fabric.Text('hello', {
fontSize: 30,
top: 10, left: 10,
originX: 0, originY: 0
});
var worldText = new fabric.Text('world!', {
fontSize: 40,
top: 50, left: 100,
originX: 0, originY: 0
});
var group = new fabric.Group([helloText, worldText], {
selectionBackgroundColor: 'red',
backgroundColor: 'blue'
});
canvas.add(group);
A jsFiddle version can be found here.
As you can see from my code, I already tried the attribute backgroundColor yet it only affects contained objects. I would like to achieve an effect similar to selectionBackgroundColor.
Slight tweak, but this should do it for you (relevant code):
var text = new fabric.Group([helloText, worldText], {});
var textBoundingRect = text.getBoundingRect();
var background = new fabric.Rect({
top: textBoundingRect.top,
left: textBoundingRect.left,
width: textBoundingRect.width,
height: textBoundingRect.height,
fill: 'blue'
});
var group = new fabric.Group([background, text], {});
Your JSFiddle updated, https://jsfiddle.net/rekrah/92ss3d86/.

I need to create object group on undo function with fabricjs

I have two canvas objects (Rectungle and Triangle) in group.
Then i need to delete them, then return one of objects to is past position.
Here is two objects and group
var rect1 = new fabric.Rect(
{
id: 1, left: 10, top: 10, width: 100, height: 50, angle: 45, fill: 'red'
});
var tria1 = new fabric.Triangle({
id: 2, left: 200, top: 200, width: 100, height: 50, angle: 20, fill: 'yellow'
});
var objsGroup = new fabric.Group([rect1, tria1], {left: 100, top: 100});
And the whole fiddle here. I separate all steps by alerts https://jsfiddle.net/5js60oec/
UPDATE
Have the next problem. Lets assume that existing object group making some move and rotating before deleting. Then i have to restore it to point before rotating and moving. Thats, i think the main problem.
Actions
objsGroup.top = 200;
objsGroup.left = 200;
canvas.renderAll();
alert('4');
history.push(canvas.getActiveGroup());
objsGroup.setAngle(45);
canvas.renderAll();
Here the full fiddler: https://jsfiddle.net/nppaLetn/1/
For example I am deleting the last added path in my canvas like below
var lastItemIndex = (fabricCanvas.getObjects().length - 1);
var item = fabricCanvas.item(lastItemIndex);
if(item.get('type') === 'path') {
fabricCanvas.remove(item);
fabricCanvas.renderAll();
}
This may help you to accomplish your probs!!! I think so .

Fabric.js: can't get the active groups anymore

I'm using fabric 1.4.10 and i noticed that i can't get the active groups anymore! Everytime i call canvas.getActiveGroup() even when a group is selected, i get null.
My code to create groups:
var circle1 = new fabric.Circle({
radius: 50,
fill: 'red',
left: 0
});
var circle2 = new fabric.Circle({
radius: 50,
fill: 'green',
left: 100
});
var circle3 = new fabric.Circle({
radius: 50,
fill: 'blue',
left: 200
});
var group = new fabric.Group([ circle1, circle2, circle3 ], {
left: 200,
top: 100
});
canvas.add(group);
Can anyone help please?
This is because you have to check for "activeObject".
fabric.canvas.getActiveObject() will return the current selected object.
getActiveGroup will return a group if there is a temporary group selection made with interactivity layer. ( mouse )
You can add these two lines code to try:
canvas._activeObject = null;
canvas.setActiveGroup(group.setCoords()).renderAll();

Categories