如何以编程方式在 javascript 中获取旋转的 svg 文本边界

How to get rotated svg text bounds in javascript programmatically

我正在动态渲染 SVG 图像并创建旋转文本。如果旋转的文本与其他文本重叠,我需要删除该文本。但我无法测量旋转的文本以创建边界并检查下一个标签文本区域。

我创建了 3 个 SVG 元素来解释。

  1. SVG-1 显示重叠文本。
  2. SVG-2 显示重叠(角度 10)的旋转文本
  3. SVG-3 显示不重叠的旋转文本(角度 50)

我会将文字动态旋转到任意角度。如果它在旋转文本时重叠,我需要以编程方式删除重叠的文本。

Fiddle link

<div style=" width: 150px;height: 150px;">

  <svg style="width: 250px; height: 144px; border: solid black 1px;">
    <text id="XLabel_0" x="75" y="30">Sprint 13_March_2015</text>
    <text id="XLabel_1" x="100" y="30">DT_Apr2015_Sprint13</text>
  </svg>

  <svg style="width: 250px; height: 144px; border: solid black 1px;">
    <text id="Label_0" x="75" y="30" transform="rotate(10, 75, 34.5)">Sprint 13_March_2015</text>
    <text id="XLabel_1" x="100" y="30" transform="rotate(10, 100, 34.5)">DT_Apr2015_Sprint13</text>
  </svg>

  <svg style="width: 250px; height: 144px; border:solid black 1px;">
    <text id="XLabel_0" x="75" y="30" transform="rotate(50,94,34.5)">Sprint 13_March_2015</text>
    <text id="XLabel_1" x="100" y="30" transform="rotate(50,123,61)" >DT_Apr2015_Sprint13</text>
  </svg>
  
</div>

谁能提出解决方案?

这可能有点棘手,但您可以计算每个文本元素的多边形,然后查看它们是否相交。 我在下面的示例中使用了您的标签之一:

<!DOCTYPE HTML>
<html>

<body>
  <svg style="width: 250px; height: 144px; border: solid black 1px;">
    <text id="label1" x="75" y="30" transform="rotate(10, 75, 34.5)">Sprint 13_March_2015</text>
    <text id="label2" x="100" y="30" transform="rotate(10, 100, 34.5)">DT_Apr2015_Sprint13</text>
    <polygon id=polygon1 fill="none" stroke="blue" stroke-dasharray="5 5" stroke-width=1 />
    <polygon id=polygon2 fill="none" stroke="red" stroke-dasharray="5 5" stroke-width=1 />
  </svg>
<br>
<button onClick=testOverlap()>Test Overlap</button>
<script>
function testOverlap()
{
    //---show 'native' rects---
    var trns1=label1.getAttribute("transform")
    label1.removeAttribute("transform")
    var bb1=label1.getBBox()
    var bb1x=bb1.x
    var bb1y=bb1.y
    var bb1w=bb1.width
    var bb1h=bb1.height
    label1.setAttribute("transform",trns1)

    var pnts1=[bb1x,bb1y,bb1x,bb1y+bb1h,bb1x+bb1w,bb1y+bb1h,bb1x+bb1w,bb1y]
    polygon1.setAttribute("points",pnts1.join())
    polygon1.setAttribute("transform",trns1)
    //---remove transform from polygon--
    ctmPolygon(polygon1)


    var trns2=label2.getAttribute("transform")
    label2.removeAttribute("transform")
    var bb2=label2.getBBox()
    var bb2x=bb2.x
    var bb2y=bb2.y
    var bb2w=bb2.width
    var bb2h=bb2.height

    label2.setAttribute("transform",trns2)
    var pnts2=[bb2x,bb2y,bb2x,bb2y+bb2h,bb2x+bb2w,bb2y+bb2h,bb2x+bb2w,bb2y]
    polygon2.setAttribute("points",pnts2.join())
    polygon2.setAttribute("transform",trns2)
     //---remove transform from polygon--
    ctmPolygon(polygon2)


    alert(getPolygonIntersect(polygon1,polygon2))

}
//---screen points for polygon---
function ctmPolygon(myPoly)
{
 var ctm = myPoly.getCTM()
 var svgRoot = myPoly.ownerSVGElement

 var pointsList = myPoly.points;
 var n = pointsList.numberOfItems;


 for(var m=0; m < n; m++)
 {
  var mySVGPoint = svgRoot.createSVGPoint();
  mySVGPoint.x = pointsList.getItem(m).x
  mySVGPoint.y = pointsList.getItem(m).y
  mySVGPointTrans = mySVGPoint.matrixTransform(ctm)
  pointsList.getItem(m).x=mySVGPointTrans.x
  pointsList.getItem(m).y=mySVGPointTrans.y
 };

 myPoly.removeAttribute("transform")
}
function getPolygonIntersect(polygonA,polygonB)
{
 var IntPoints=[]
 var aPoints=polygonA.points
 var m=aPoints.numberOfItems
 for(var i=0;i<m;i++)
 {
  var aX1=aPoints.getItem(i).x
  var aY1=aPoints.getItem(i).y

  if(i<m-1)
  {
   var aX2=aPoints.getItem(i+1).x
   var aY2=aPoints.getItem(i+1).y
  }
  else
  {
   var aX2=aPoints.getItem(0).x
   var aY2=aPoints.getItem(0).y
  }

  var bPoints=polygonB.points
  var n=bPoints.numberOfItems

  for(var k=0;k<n;k++) //--each side of polygon---
  {
   var bX1=bPoints.getItem(k).x
   var bY1=bPoints.getItem(k).y

   if(k<n-1)
   {
    var bX2=bPoints.getItem(k+1).x
    var bY2=bPoints.getItem(k+1).y
   }
   else
   {
    var bX2=bPoints.getItem(0).x
    var bY2=bPoints.getItem(0).y
   }
   //---return false or intersect point---
   var xy=lineSegIntersect(aX1,aY1,aX2,aY2,bX1,bY1,bX2,bY2)
   if(xy)
   {
    if(IntPoints.join().indexOf(xy)==-1)//--no dups--
    {
     IntPoints.push(xy)
    }

   }
  }
 }
    if(IntPoints.length>0)
        return true
    else
        return false
}
//---compare two lines: A.B---
function lineSegIntersect(aX1,aY1,aX2,aY2,bX1,bY1,bX2,bY2)
{
 //---compute vectors Va, Vb--------
 var Va=( (bX2-bX1)*(aY1-bY1) - (bY2-bY1)*(aX1-bX1) )/ ( (bY2-bY1)*(aX2-aX1) - (bX2-bX1)*(aY2-aY1) )
 var Vb=( (aX2-aX1)*(aY1-bY1) - (aY2-aY1)*(aX1-bX1) )/( (bY2-bY1)*(aX2-aX1) - (bX2-bX1)*(aY2-aY1) )

 if(Va>0 && Va<1 && Vb>0 && Vb<1)
 {
 //---intersect true, show point---
  var ma=(aY2-aY1)/(aX2-aX1)
  var mb=(bY2-bY1)/(bX2-bX1)
  if(aX2!=aX1&&bX2!=bX1) //---!vertical line---
  {
   var x=(aX1*ma-aY1-bX1*mb+bY1)/(ma-mb)
   var y=ma*(x-aX1)+aY1
  }
  else if(aX2==aX1)
  {
   var x=aX1
   var y=mb*(x-bX1)+bY1
  }
  else if(bX2==bX1)
  {
   var x=bX1
   var y=ma*(x-aX1)+aY1
  }

  return [x,y]
    }
 else
 return false
}

</script>
</body>

</html>