Fabric.js: Get absolute position

Created on 22 Aug 2013  Â·  25Comments  Â·  Source: fabricjs/fabric.js

I have a component inside of a group. Its coordinates is relative to the group. How can I get its absolute position, or, in another words, the relative position to the canvas?

Maybe a element.getParent() could help too. Any suggestion?

Sorry by the too newbie question and thanks in advance.

Most helpful comment

I agree than an extend tutorial on coordinates and transformations is needed.

All 25 comments

All objects in a group have reference to it — object.group. So you can get left/top of a group, which is its center. And you can get left/top of each object within a group, which is relative to group's left/top corner. After that, it's just: group.left + object.left, group.top + object.top, etc.

Is there any built-in utilites to get objects relative-to-group position as if group had different (arbitrary) originX and originY?

Actually the solution @kangax provided won't work if advanced transformations were applied to the group. In that case you'll need to do some calculations yourself and/or use built-in methods of fabric.util, as rotatePoint .

Can you describe how can you use rotatePoint to fix this problem ?
If we just sum the group position with object position this will not work when we rotate or scale the group.

Also, what I have seen is that when you scale or rotate an object (from controls) that was selected and modified before from a group then you can get the correct positions .

Was just coping with a similar issue for a few whiles and I've finally found out that you can discard a group (discarding it will recalculate coordinates, angle and stuff for the objects) and then rebuild it afterwards, like so (found in fabric.Canvas' serialization method):

if (oldGroup) {
    canvas.setActiveGroup(new fabric.Group(oldGroup.getObjects(), {
        originX: 'center',
        originY: 'center'
    }));
    oldGroup.forEachObject(function(o) {
        o.set('active', true);
    });

    if (canvas._currentTransform) {
        canvas._currentTransform.target = canvas.getActiveGroup();
    }

    canvas.renderAll();
}

can we have a function like getAbsolutePosition(obj) which returns {x: x, y: y}. or add absoluteLeft and absoluteTop properties to objects, because I need to get absolute position of every object in the group and calculating everything myself with fabric.util.rotationPoint is kinda annoying.

What do you mean by absolute position of object in group? if you explain me with a drawing ( paper + pen + picture is ok ) i will tell you how to do it. there is no builtin method but you can write your own easily

by absolute I mean relative to canvas

Top Left of object or top left of bounding box of object? ( imagine a rect rotated of 45°, what is top left for you? )

Top left of object

thx to @asturur i was able to make it work

for originX: center and originY: center

function getAbsolutePosition(obj) {
        var m = obj.calcTransformMatrix();

        return {left: m[4], top: m[5]};
    }
}

2485

i think that m4 and m5 represent the translate effect that gets applied to -width/2 and -height/2 of the object.... i'm not sure they are actually top and left.

@AshtonRoute and @asturur: You are correct, it is not exactly top and left. Using the code from AshtonRoute, is there an alternative that would give top & left? It's super close and works as intended, but it's not actually correct :(

FYI: I am doing remote sync with a 2nd client (other browser). This was the best solution to perform updates to objects without worrying about groups, but the m4/m5 combo is still a few yards from a touchdown. Any ideas?

FYI: @AshtonRoute and @asturur : This did the trick: How to get the canvas relative position of an object that is in a group

o.set('left',o.left + o.group.left + o.group.width/2);
o.set('top',o.top + o.group.top + o.group.height/2);

I just wanted to add a +1 on to here. I definitely have the need to obtain canvas-relative coordinates while multiple objects are selected.

I find it difficult to manage when the coordinate system changes for a given object while it is in a group -- I would prefer a mode/setting where the coordinates are always canvas relative, like when an object is not selected.

An example use case -- I am drawing a selectable object that has a non-selectable object follow it along. I position this second object using events ('moving', 'modified') and calculate its position relative to the selectable object. This works great for single selections.

But, if I have two of those selected, now none of my code works because if I try to calculate the position of the 'following' object, the selectable objects both return group-relative positions.

Wouldn't it make sense for objects to have some method that returns x- and y-coordinates, widths and heights with respect to the canvas, which is that most developers will be interested in. Now developers need to code all the nested scaling and translating that is done in groups, highly likely resulting in buggy code, since most developers are users and not experts of fabric.js.

I would also welcome an easy way of getting canvas relative positions. I have been struggling for many hours because the coordinates of selected objects were different than the others, until I finally found out. Currently when I have to read those coordinates I empty the selection, which is not optimal.

I also think that most developers would expect all coordinates to be relative to the canvas. Besides, it's only mentioned very briefly in the tutorial, which makes it hard for developers new to fabric.js to remember or even pay attention to this particular behaviour.

I agree than an extend tutorial on coordinates and transformations is needed.

I'm building a "look" constructor, where you can drop some clothing on canvas and save it. Plus I save all geometry to server, since the same look can be displayed on mobile.

Each time object is modified I update a special property "geometry" which I send to the server.

All I need is absolute left/top, but there is no method for this. Of course it is possible to calculate them but this is definitely is not convenient :(

every absolute coordinate must be calculated, from you or library, there is no shortcut to calculation

if you need just the corners you have the .aCoords object that contains it

Yeah, but I also need scale and other stuff as well. Though I decided just to re-read coordinates after selection is cleared, kind of workaround :)

o.set('left',o.left + o.group.left + o.group.width/2);
o.set('top',o.top + o.group.top + o.group.height/2);

Your solution working well, thank bro!

FYI: @AshtonRoute and @asturur : This did the trick: How to get the canvas relative position of an object that is in a group

o.set('left',o.left + o.group.left + o.group.width/2);
o.set('top',o.top + o.group.top + o.group.height/2);

thanks man, I've been looking for this solution..

This won't work outside the very simple cases.

for the object that is any group, the position of the top left corner is, for example:

// 1. get the matrix for the object.
var matrix = ObjectInGroup.calcTransformMatrix();
// 2. choose the point you want, fro example top, left.
var point = { x: -ObjectInGroup.width/2, y: ObjectInGroup.height/2 };
// 3. transform the point
var pointOnCanvas = fabric.util.transformPoint(point, matrix)
Was this page helpful?
0 / 5 - 0 ratings

Related issues

medialwerk picture medialwerk  Â·  5Comments

eugene-g13 picture eugene-g13  Â·  3Comments

mlev picture mlev  Â·  3Comments

amancqlsys picture amancqlsys  Â·  5Comments

urcoder picture urcoder  Â·  5Comments