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

时间:2017-03-20 10:36:13

标签: javascript jquery html5 svg trigonometry

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

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

  1. SVG-1显示重叠的文字。
  2. SVG-2显示重叠(角度-10)
  3. 的旋转文本
  4. SVG-3显示未重叠的旋转文本(角度-50)
  5. 我会动态地将文本旋转到任意角度。如果在旋转文本时它重叠,我需要以编程方式删除重叠的文本。

    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>

    有人可以建议解决方案吗?

1 个答案:

答案 0 :(得分:5)

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

<!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>