Usually in order to get bounding box of any element in SVG we use getBoundingClientRect() or getBBox() which gives us top, bottom, left, right, width, height or x, y, width, height respectively. But when the text is rotated these values are not enough to get tight bounding box of the element as box formed by these values will have horizontal and vertical edges, not parallel to the text. How can the tight bounding box be selected for a rotated text as shown in the image below. (The text was highlighted by Chrome Inspect Element Selector.)
-
A testing code example would be useful. Not quite sure if you are meaning just for display, eg can't you just rotate the bounding box as well ? Maybe the question is also what else you want to do with it ? – Ian May 25 '17 at 14:32
-
in short I just need the four points(x,y) of the bounding box (not x, y width and height), so that I can know where exactly my text is in the plane and how much space is there to work on. – Ankit Kumar Ojha May 26 '17 at 06:08
3 Answers
I think if you want the 4 points, you may have to transform them on the bounding box with the same transform as the element. If it's just for display, just apply the same transform to a bounding box that has been displayed. I think if you want the 4 points, it's a bit more complicated, but there may be a simpler way.
This may be useful anyway.
We grab the bounding box of the text. We grab the matrix (in this case rotation) on the element. Then we apply that to all the points we gather from the bounding box. I've added a bit more code, just to create circles at the points, to highlight it.
var text = document.querySelector('text');
var svg = document.querySelector('svg')
function getTransformedPts( el ) {
var m = el.getCTM();
var bb = el.getBBox();
var tpts = [
matrixXY(m,bb.x,bb.y),
matrixXY(m,bb.x+bb.width,bb.y),
matrixXY(m,bb.x+bb.width,bb.y+bb.height),
matrixXY(m,bb.x,bb.y+bb.height) ]
return tpts;
}
function matrixXY(m,x,y) {
return { x: x * m.a + y * m.c + m.e, y: x * m.b + y * m.d + m.f };
}
var pts = getTransformedPts( text );
for( pt in pts ) {
var c = document.createElementNS("http://www.w3.org/2000/svg","circle");
c.setAttribute('cx', pts[pt].x);
c.setAttribute('cy', pts[pt].y);
c.setAttribute('r',3)
svg.append(c)
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="800" height="800">
<text x="50" y="50" transform="rotate(10)" font-size="30">testing rotated text box points</text>
</svg>

- 13,724
- 4
- 52
- 75
If you are getting the bounding box of a <text>
element using getBBox()
, then it normally is the unrotated bounding box. That's because getBBox()
does not include the elements transform
when calculating the value to return.
For example, have a look at the example below. Compare the text BBox and the BBox of its parent group element.
var text = document.getElementById("text");
var b = text.getBBox();
console.log("text bbox="+[b.x,b.y,b.width,b.height].join(' '));
var group = document.getElementById("group");
var b = group.getBBox();
console.log("group bbox="+[b.x,b.y,b.width,b.height].join(' '));
<svg width="300" height="300">
<g id ="group">
<text id="text" x="150" y="150" text-anchor="middle" font-size="30"
transform="rotate(45,150,150)">ROTATED</text>
</g>
</svg>

- 97,474
- 9
- 154
- 181
There is no direct method to achieve this. But you can try the below solution.
How to get rotated svg text bounds in javascript programmatically

- 4,534
- 3
- 20
- 25