How get tight bounding box of an SVG Text Element

旧城冷巷雨未停 提交于 2019-12-12 13:33:05

问题


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


回答1:


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>



回答2:


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>



回答3:


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



来源:https://stackoverflow.com/questions/44178791/how-get-tight-bounding-box-of-an-svg-text-element

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!