Normally an object's position relative to the canvas can be gotten from it's .left
and .top
attributes, but these become relative to the group if the object is in a selection/group. Is there a way to get their position relative to the canvas?

- 3,169
- 4
- 32
- 55
-
Is this what you are looking for? http://jsfiddle.net/uue3hcj6/3/ As you said they become relative to the group, you can use the group's left and top to find the absolute position on the canvas. – Swapnil Jain Apr 25 '15 at 16:19
-
This doesn't seem to work with selections: http://jsfiddle.net/uue3hcj6/4/ – Jasper van den Bosch Apr 26 '15 at 18:31
-
@SwapnilJain Do you know why the values in the second one don't work? – Jasper van den Bosch Apr 26 '15 at 18:32
-
1all this depends on what origin is set for the object/group. In the 1st fiddle, I set the group origin to center. Which is why I didn't add 1/2 of group's width to the calculations (group.left gave me distance of its center from the canvas left). But by default origin is set to top/left. Hence for the selections(your case) or groups without origin set to center, group.left is distance of group's left from canvas left. Now why do I need to add half of group's width to the calculations? This is because object.left is a measurement of left of object from group's center. – Swapnil Jain Apr 27 '15 at 04:57
-
1Probably this might explain better: group's origin set to center: http://i.imgur.com/csLtv7U.png vs group's origin set to top/left(default): http://i.imgur.com/PY0JJfo.png – Swapnil Jain Apr 27 '15 at 05:17
-
1@SwapnilJain Thanks for explaining! I understand now, I didn't see what "originX" meant before. If you make this into an answer and ping me, I'll mark your answer as the solution – Jasper van den Bosch Apr 27 '15 at 20:17
-
Thanks, I have posted the answer. – Swapnil Jain Apr 28 '15 at 17:54
6 Answers
When an object is inside a group, its coordinates relative to the canvas will depend on the origin of the group (and origin of the object as well).
Lets say we have this code which has a rect and a circle added to a group.
var canvas = new fabric.Canvas(document.getElementById('c'));
var rect = new fabric.Rect({
width: 100,
height: 100,
left: 50,
top: 50,
fill: 'rgba(255,0,0,0.5)'
});
var circle = new fabric.Circle({
radius: 50,
left: 175,
top: 75,
fill: '#aac'
});
var group = new fabric.Group([rect, circle],{
originX: 'center',
originY: 'center'
});
canvas.add(group);
canvas.renderAll();
Below are the three cases possible for centering the group:
Origin of group set to center(as in the code above):
As shown in the figure below,
rect.left
gives us distance of left of object from center of the group.rect.group.left
gives us the distance of center of group from left of canvas.So distance of rect from left of canvas =
rect.left + rect.group.left
(http://jsfiddle.net/uue3hcj6/3/)Origin of group is set to top/left (also the default setting)
rect.left
gives us distance of left of object from center of the group.rect.group.left
gives us the distance of left of group from left of canvas. Now to calculate the remaining distance, we have to add half of width of the group.So distance of rect from left of canvas =
rect.left + rect.group.left
+rect.group.width/2
(http://jsfiddle.net/uue3hcj6/6/)Origin of group is set to bottom/right
rect.left
gives us distance of left of object from center of the group.rect.group.left
gives us the distance of right of group from left of canvas. Now to calculate the total distance, we have to subtract the half of width of the group.So distance of rect from left of canvas =
rect.left + rect.group.left
-rect.group.width/2
(http://jsfiddle.net/uue3hcj6/7/)
Note: Similar cases are possible for object as well.

- 1,456
- 12
- 19
-
-
I don't understand something though. In your first example if we change the left of circle, for instance, and add angle to group, the position of the rectangle is changed too! I'm trying to fix all the objects inside the group and rotate the group itself around its center, but for some reason all objects moving not fixed and I can't figure out why. – Kath May 20 '16 at 21:57
-
4and what about nested groups?... is it such a rare function we have to invent our own bicycle? :| – let4be May 24 '16 at 21:04
-
it was helpful conceptually, but as translations and transformations are applied, there are lot to do over top of it. as someone pointed out to use calcTransformMatrix that gives the coordinate for same. https://stackblitz.com/edit/angular-sn3g7w?file=src%2Fmain.ts – Vikas Feb 01 '23 at 06:18
just as a complement to Swapnil Jain's answer the same goes for the top
attribute.
So:
absoluteLeft = rect.left + rect.group.left - rect.group.width / 2
absoluteTop = rect.top + rect.group.top - rect.group.height / 2

- 4,519
- 4
- 29
- 45
There is universal way to calculate position of any object on canvas regardless groups and origin:
const position = fabric.util.transformPoint(
// you can choose point of object (left/center/right, top/center/bottom)
object.getPointByOrigin('left', 'top'),
object.calcTransformMatrix()
)

- 162
- 5
-
Does not work for me, even if it looks the most correct answer. 1. If i have a object without group the resulting coordinates are in x and y double the value. 2. If i have a group it is disposed by the half of the groupsize. – Grim Feb 02 '22 at 11:54
The solution is to take into account the group width. The object.left
is relative to the group's center, not it's left side, so we take group.width/2
:
var canvas = new fabric.Canvas(document.getElementById('c'));
var rect = new fabric.Rect({
width: 100,
height: 100,
left: 50,
top: 50,
fill: 'rgba(255,0,0,0.5)'
});
var circle = new fabric.Circle({
radius: 50,
left: 150,
top: 75,
fill: '#aac'
});
canvas.add(rect);
canvas.add(circle);
canvas.renderAll();
function getPOS(){
var group = canvas.getActiveGroup();
if (group == null) {
var pos = rect.left;
}
else {
var pos = rect.group.left + rect.group.width/2 + rect.left;
}
alert("Position of rect from left:"+pos);
}

- 3,169
- 4
- 32
- 55
Had to solve this issue with another approach... I had to find images in JSON canvas data, so my code is:
let findItemByType = function(source, type, rX, rY)
{
rX = rX ? rX : 0;
rY = rY ? rY : 0;
let objs = [];
source.forEach(function(item){
if (item.type === type){
item.rX = rX + item.left;
item.rY = rY + item.top;
objs.push(item);
}
else {
if (item.objects)
{
item.rX = rX;
item.rY = rY;
let subresult = findItemByType(item.objects,
type,
item.rX + item.left + item.width / 2,
item.rY + item.top + item.height / 2);
if (subresult){
objs = objs.concat(subresult);
}
}
}
});
return objs;
}
let images = findItemByType(canvas.toJSON().objects, "image", 0, 0);
This code should bring an array of all image objects and they should have rX and rY attributes which is relative positions of images.

- 1
- 2
A method that does not need to judge the originX originY attribute.
const groupCenter = rect.group.getPointByOrigin('center', 'center');
absoluteLeft = rect.left + rect.group.left;
absoluteTop = rect.top + rect.group.top;

- 16
- 2