getBBox() not working consistently

1,486 views
Skip to first unread message

Vicent Ortega

unread,
Jan 18, 2016, 10:46:56 AM1/18/16
to Snapsvg

The getBBox() function of Snap is really awesome as it does what the browsers should have done when they implemented getBoundingClientRect(), but it's behaving extrangely when it comes to do it's work with groups. That is:


<ellipse id="elli" cx="200" cy="200" rx="100" ry="50" stroke="black" fill="none" transform="rotate(30, 200, 200)"></ellipse>


I use getBBox() on it and everything is allright:


var elli = paper.select('#elli');
var box = elli.getBBox();
d.rect(box.x, box.y, box.width, box.height).attr({stroke: 'red', fill: 'none'});


after this code the red box appears completly stick to the rotated ellipse, but if I change the markup to this:


<g id="elli" transform="rotate(30, 200, 200)">

    <ellipse cx="200" cy="200" rx="100" ry="50" stroke="black" fill="none"></ellipse>

</g>


then the red box behaves as it was surrounding the BoundingClientRect, that is bigger than the ellipse, so the red box sides are separated from the ellipse.

Is this a bug or is it the intended behaviour?

I need to get the boundings of a set of figures inside a group and I can't manage to do now.

Ian

unread,
Jan 18, 2016, 10:50:35 AM1/18/16
to Snapsvg
Not sure if this got sent late, but I think I replied to it here a few days ago...

Vicent Ortega

unread,
Jan 18, 2016, 12:17:16 PM1/18/16
to Snapsvg
I've answered in the issue you're linking, but also I'll post the answer here:

Maybe I haven't described the issue correctly or we are not understanding each other.
I've prepared a CodePen to clarify the issue. Please, see it here:


CodePen Example


The correct behaviour SHOULD be that the two red boxes were equal, like in case 1. Isn't it?

Ian

unread,
Jan 18, 2016, 12:34:52 PM1/18/16
to Snapsvg
Yes and no as mentioned, as the browser implementations are different. 

I'm not sure if its because the browsers differ in what they think is correct according to the spec, or whether one has a bug. I assume the latter, and that should be reported to the respective browser bug trackers, but sometimes they disagree on what the spec says.

I know thats not all that helpful to you, and its pretty annoying when you see issues like this, I'm just explaining why its happening, and libraries have to rely on a certain amount of native functions I think.

So realistically I would suggest finding a hack around it, or coding a separate func for it, as I doubt this one is going to get fixed by anyone in the short term, and I assume it will be the same in every svg library out there. 

Ian

unread,
Jan 18, 2016, 12:39:42 PM1/18/16
to Snapsvg

Ian

unread,
Jan 18, 2016, 2:31:00 PM1/18/16
to Snapsvg
Just stepping back, can't you get the bbox from the ellipse itself rather than the group as a workaround ?

Vicent Ortega

unread,
Jan 19, 2016, 5:09:58 AM1/19/16
to Snapsvg
Thanks for you time and effort, Ian.

Taking a geometric approximation is not an option for us, because the ellipse case is just an example. We have many other cases with all kinds of shapes, and make a different caluculus for each one would be eternal...
We can't change the structure also, as each of this shapes could be combined in a group that represents and object, wich is bound to the document by means of an AngularJS model, so we can make change tracking easily. We've used a declarative approach with the SVGs instead the imperative approach of Snap, Raphael and most libraries out there.

We just got Snap because it effectively calculated the correct bounding rectangle that the getBoundingClientRect() doesn't do. But I think it just have a bug when it comes to groups. It is accumulating the bboxes of the elements inside the group and then applying the transformations of the group to the resulting bbox, and that's not correct. It should iterate over the shapes on the gruops and accumulate its bboxes taking into account their accumulated translation and rotation, as it does when there is no gruop.
This is true if we make the assumption that the bbox must be paralell to the viewport, or maybe I'm wrong with this...

Ian

unread,
Jan 19, 2016, 5:34:32 AM1/19/16
to Snapsvg
Just guessing then, if there can be multiple elements inside the group all of different shapes...

Use another method like getBoundingClientRect and transform the coordinates from here, to the required coordinate space, not sure why this wouldn't work, but haven't played with that getBCR before...

Find the getBBox of the elements inside the group and map through them all to find the maximum x1,x2,y1,y2 (you could possibly do this once and then store those values on the object so you don't need to repeat it if it moves, you just transform the bounding box the same as the group or whatever)

Some other solution that hasn't popped into mind yet.
Message has been deleted

Vicent Ortega

unread,
Jan 19, 2016, 6:49:57 AM1/19/16
to Snapsvg
getBoundingClientRect() was the reason that we're using SnapSVG. It's completly broken for rotated curves, etc. The only good implementation was from Mozilla Firefox three years ago, but they changed it to accomodate the wrongly, but most used, Chrome and Explorer implementations.

Snap getBBox() makes it perfectly for a single shape with whatever transformations it has. But when it comes to groups it fails, as it accumulates the bboxes and then transforms, instead of accumulating the transformed bboxes. I'm pretty sure it's a bug. But I don't know how to fix it.

I haven't found anywhere in the code on Github where it processes the elements inside a group  (forget about my later message, I've just deleted it, it was wrong)

Vicent Ortega

unread,
Jan 19, 2016, 6:58:04 AM1/19/16
to Snapsvg
Just change the ellipse for a simple circle. Put it inside a rotated group and get the bbox...  It's absurd!!!

Ian

unread,
Jan 19, 2016, 11:07:21 AM1/19/16
to Snapsvg
I'm not sure accumulating transformed bboxes would be right either.

If you think about the circle example, if you accumulate bboxes and then transform its wrong, If you accumulate transformed bboxes its wrong. The only way I can figure it would be right, is if the points of whatever shapes are transformed and then a none transformed bounding box is used (which I assume is what bbox does on a direct element).

It feels like whichever way you swing it, unless there is some function that will transform the initial points shape into the correct coordinate space (which is of course possible but a task in itself I think), it will be difficult.


Reply all
Reply to author
Forward
0 new messages