Hi Stack overflowers:)
我正在努力使用svg多边形对象,我需要能够(按比例)调整大小,并保存/设置新的点值。目前我可以通过将CSS变换应用于SVG对象来实现此目的,但这不会更改points属性值。这有可能吗?我的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>
提前致谢:)
答案 0 :(得分:1)
好吧,你可以通过偏移(+/-)像素值扩展/收缩多边形,这将改变它的点值。有问题的多边形必须是凸的。 此外,下面的示例可以缩放多边形,然后使用矩阵变换在缩放变换后重新计算其点。
尝试以下内容
<!DOCTYPE HTML>
<html>
<head>
<title>Resize Convex Polygon</title>
</head>
<body>
<center>
Offset(+/-) 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>
&#13;