How get tight bounding box of an SVG Text Element

2019-07-14 18:55发布

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.)

3条回答
女痞
2楼-- · 2019-07-14 19:01

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

查看更多
可以哭但决不认输i
3楼-- · 2019-07-14 19:02

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>

查看更多
做个烂人
4楼-- · 2019-07-14 19:10

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>

查看更多
登录 后发表回答