【问题标题】:SVG polygon scale and set points accordinglySVG 多边形比例和相应的设置点
【发布时间】:2016-11-26 07:17:21
【问题描述】:

你好堆栈溢出 :)

我正在努力处理一个 svg 多边形对象,我需要能够(按比例)调整大小,并保存/设置新的点值。目前我可以通过对 SVG 对象应用 CSS 变换来做到这一点,但这不会改变点属性值。这有可能吗?我的 SVG 多边形如下所示:

<svg viewBox="0 0 100 100" style="width: 100px; height: 100px;">
  <polygon fill="black" points="0,0 50,0 100,100 0,100" />
</svg>

提前致谢:)

【问题讨论】:

  • 这是什么意思? SVG 是矢量图形,因此可以在不改变点的情况下调整大小。你能指定你的用例吗?
  • 这些点需要存储在数据库中以便在另一个前端渲染,这就是我需要这些多边形坐标的原因:)

标签: javascript html css svg polygon


【解决方案1】:

好吧,您可以通过偏移 (+/-) 像素值扩展/收缩多边形,这将改变其点值。所讨论的多边形必须是凸的。 此外,下面的示例可以缩放多边形,然后使用矩阵变换在缩放变换之后重新计算其点。

试试下面的

<!DOCTYPE HTML>

<html>

<head>
  <title>Resize Convex Polygon</title>
</head>

<body>
<center>
    Offset(+/-)&nbsp;px.<input type="text" style="width:50px" id=offsetValue value=10 /><button onClick=resizeMyPolygon()>Resize Polygon</button>
      <br>
      <button onClick=scalePolygon() >Scale Polygon</button>
      <br>

<svg xmlns="http://www.w3.org/2000/svg" id="mySVG" width="600" height="600">
<polygon id="myPolygon" fill="yellow" stroke="black" stroke-width="1" points="380,80 200,10 40,80 100,320 300,350"></polygon>
<svg>
</center>
 <script>
 //---button---
 function scalePolygon()
 {
    //---scale from center of polygon--
    var bb=myPolygon.getBBox()
    var bbx=bb.x
    var bby=bb.y
    var bbw=bb.width
    var bbh=bb.height
    var cx=bbx+.5*bbw
    var cy=bby+.5*bbh
    myPolygon.setAttribute("transform","translate("+cx+" "+cy+")scale(1.2)translate("+(-cx)+" "+(-cy)+")")

    screenPolygon(myPolygon)
    console.log(myPolygon.getAttribute("points"))

 }
function screenPolygon(myPoly)
{
	var sCTM = 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(sCTM)
		pointsList.getItem(m).x=mySVGPointTrans.x
		pointsList.getItem(m).y=mySVGPointTrans.y
	};
	//---force removal of transform--
	myPoly.setAttribute("transform","")
	myPoly.removeAttribute("transform")
}

 //---button---
function resizeMyPolygon()
{
    var pointList=myPolygon.points
    //---clockwise or counterclockwise--
    function polygonArea() {
    var area = 0;
    for (var i = 0; i < pointList.length; i++) {
        j = (i + 1) % pointList.length;
        area += pointList.getItem(i).x * pointList.getItem(j).y;
        area -= pointList.getItem(j).x * pointList.getItem(i).y;
    }
    return area / 2;
    }
    var clockwise = polygonArea() > 0;  //---false is ccw points--

    var offset=parseFloat(offsetValue.value)

    if((offset>0&& clockwise==true)||(offset<0&&clockwise==false))
    {
        //--reverse polygon points---
        var pointArray=[]
        for(var k=pointList.numberOfItems-1;k>=0;k--)
        {
            var lastPnt=pointList.getItem(k)
            pointArray.push([lastPnt.x,lastPnt.y])
        }
        myPolygon.setAttribute("points",pointArray.join() )
        pointList=myPolygon.points
    }


    var changedPoints=resizePolygon(pointList,offset,mySVG)
    myPolygon.setAttribute("points",changedPoints.join() )
    console.log(myPolygon.getAttribute("points"))
}

function resizePolygon(pointsList,offset,rootSVG)
{
	var m=pointsList.numberOfItems
	//---first find centroid---
	var total_area = 0;
	var centroid = [0, 0];
	var a = pointsList.getItem(0);
	for (i = 0; i < m - 2; i++)
	{
		var b = pointsList.getItem(i + 1)
		var c = pointsList.getItem(i + 2);
		var area = 0.5 * Math.abs((a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y));
		total_area += area;
		centroid[0] += area * (a.x + b.x + c.x);
		centroid[1] += area * (a.y + b.y + c.y);
	}
	centroid[0] /= total_area * 3;
	centroid[1] /= total_area * 3;

	var points_offset = [];
	for (i = 0; i < m; i++)
	{
		//--- a-b is a line segment on the convex polygon---
		var a = pointsList.getItem(i);
		var b = pointsList.getItem(i == m - 1 ? 0 : i + 1);

		//---Determine the normal to the line segment---
		var slope = -1 / ((b.y - a.y) / (b.x - a.x));

		//---Construct a new line d--e that is the line a--b shifted 'offset'---
		//---units in the direction of the normal---
		var w, h;
		if (a.y == b.y)
			w = 0;
		else
	   		w = (a.y < b.y ? -1 : 1) * Math.sqrt(offset * offset / (1 + slope * slope));

		if (w == 0)
			h = (a.x > b.x ? -1 : 1) * offset;
		else
			h = slope * w;

		//---root svg element---
		var d=rootSVG.createSVGPoint()
		var e=rootSVG.createSVGPoint()
		d.x = a.x + w
		d.y = a.y + h

		if (slope == 0)
		{
			e.x = d.x
			e.y=d.y + 10
		}
		else
		{
			e.x = d.x + 10,
			e.y=d.y - 10 / slope
		}

		//---Intersect the line d--e with centroid--a, which is the point on---
		//---the inflated convex polygon---
		//---http://en.wikipedia.org/wiki/Line-line_intersection---
		points_offset.push([
		((d.x * e.y - d.y * e.x) * (centroid[0] - a.x) - (d.x - e.x) * (centroid[0] * a.y - centroid[1] * a.x))
		/ ((d.x - e.x) * (centroid[1] - a.y) - (d.y - e.y) * (centroid[0] - a.x)),
		((d.x * e.y - d.y * e.x) * (centroid[1] - a.y) - (d.y - e.y) * (centroid[0] * a.y - centroid[1] * a.x))
		/ ((d.x - e.x) * (centroid[1] - a.y) - (d.y - e.y) * (centroid[0] - a.x))
		]);
	}
	return points_offset
}

 </script>
 </body>
</html>

【讨论】:

  • 谢谢@francis,你让我走上了正确的道路:)
猜你喜欢
  • 2016-02-07
  • 2017-08-22
  • 2016-08-13
  • 1970-01-01
  • 1970-01-01
  • 2013-07-23
  • 1970-01-01
  • 2018-06-08
  • 1970-01-01
相关资源
最近更新 更多