javascript - SVG 多边形缩放并相应地设置点

标签 javascript html css svg polygon

嗨 Stack overflowers :)

我正在努力处理一个 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>

提前致谢:)

最佳答案

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

试试下面的方法

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

关于javascript - SVG 多边形缩放并相应地设置点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38525536/

相关文章:

javascript - 使用 jQuery 进行表格分页

javascript - IE11是否支持window.postMessage()

css - 多行 HTMLanchors 中的不可点击区域

javascript - Canvas drawImage 不起作用,但 fillrect 起作用

PHP/HTML 动态页面/搜索

JavaScript 对象 - 不同类型取决于上下文

javascript - Angular 拦截器 - 从 500 错误获取消息

javascript - ES6 使用 --experimental-modules 在 Node 中导入

html - 如何为设备设置边距/填充

html - 页面 View 调用托管字体