Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get rotated svg text bounds in javascript programmatically

I am rendering SVG image dynamically and created rotated text. If the rotated text is overlap with other text, i need to remove that text. But i can't measure the rotated text to create bounds and check with next label text region.

I have created 3 SVG element to explain.

  1. SVG-1 Shows the overlapped text.
  2. SVG-2 Shows the rotated text with overlapped (Angle-10)
  3. SVG-3 Shows the rotated text without overlapping (Angle-50)

I will rotate the text to any angle dynamically. If it is overlapped while rotating text, I need to remove that overlapped text programmatically .

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>

Can anyone suggest a solution?

like image 707
Bharathi Avatar asked Mar 20 '17 10:03

Bharathi


1 Answers

It can be kinda tricky, but you can compute polygons for each text element, and then see if they intersect. I used one of your labels in the example below:

<!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>
like image 182
Francis Hemsher Avatar answered Sep 20 '22 18:09

Francis Hemsher