说我有以下SVG:
<g id="g1" transform="translate(100, 250) rotate(90)" >
<path id="path1" d="M 100,100 c...
有没有办法获得d属性的实际坐标?理想情况下,我想要一些功能,如下面的untransform
:
var transform = $("g1").getAttribute("transform");
var d = $("path1").getAttribute("d");
var dUntransformed = untransform(d, transform);
$("g1").removeAttribute("transform");
$("path1").setAttribute("d", dUntransformed);
我的想法是,如果我运行此脚本,生成的图像将与之前的图像相同。
我想这样做的原因是因为我有一个遵循这条路径的动画。但是由于变换,动画关闭了。如果我将变换添加到animateMotion对象,则动画仍然关闭。所以我的想法是删除路径并将其准确地放回原处。这样我就可以让动画工作了。 (AnimateMotion与此演示类似:https://mdn.mozillademos.org/files/3261/animateMotion.svg)
答案 0 :(得分:2)
以下是转换后返回屏幕点的示例:polygon,path,polyline。路径示例不起作用或弧。此外,在某些情况下,相对点可能不会返回。这使用getCTM
和matrixTransform
。可以创建一个数组来“记住”各个时间线上的点。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Return Screen Points After Tranformations</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body style='padding:0px;font-family:arial'>
<center>
<h4>Return Screen Points After Tranformations : polygon, path, polyline</h4>
<div style='width:90%;background-color:gainsboro;text-align:justify;padding:10px;border-radius:10px;'>
In many cases it is meaningful to return certain svg elements(polygon, polyline, and path) to their screen x,y values following transformations. This is accomplished using <b>getCTM</b>, and <b>matrixTransform</b>
Note: Use vector-effect="non-scaling-stroke" for elements with stroke(*not available in IE).
</div>
<div id="svgDiv" style="background-color:lightgreen;width:500px;height:500px;">
<svg id="mySVG" width="500" height="500">
<path id="myPath" vector-effect="non-scaling-stroke" transform="scale(.8)translate(120 50)skewY(15)rotate(-15)" fill="yellow" stroke="black" stroke-width="2"
d="M50,50 Q-30,100 50,150 100,230 150,150 230,100 150,50 100,-30 50,50"/>
<polyline vector-effect="non-scaling-stroke" id="myPolyline" transform="scale(.3)translate(700 620)" fill="red" stroke="black" stroke-width="3" points="122 60 150 450 500 400" />
<polygon vector-effect="non-scaling-stroke" id="myPolygon" transform="scale(3)translate(122 132)" fill="purple" stroke="white" stroke-width="3"points="15,0 10.6066,-10.6066 9.18486e-016,-15 -10.6066,-10.6066 -15,-1.83697e-015 -10.6066,10.6066 -2.75545e-015,15 10.6066,10.6066" />
</svg>
</div>
<button onClick=change2Screen()>change to screen values</button>
<br />SVG Source:<br />
<textarea id=mySVGValue style='font-size:120%;font-family:lucida console;width:90%;height:200px'></textarea>
<br />Javascript:<br />
<textarea id=jsValue style='border-radius:26px;font-size:110%;font-weight:bold;color:midnightblue;padding:16px;background-color:beige;border-width:0px;font-size:100%;font-family:lucida console;width:90%;height:400px'></textarea>
</center>
<div id='browserDiv' style='padding:3px;position:absolute;top:5px;left:5px;background-color:gainsboro;'></div>
<script id=myScript>
//--button---
function change2Screen()
{
screenPolyline(myPolyline)
screenPolygon(myPolygon)
screenPath(myPath)
mySVGValue.value=svgDiv.innerHTML
}
function screenPolyline(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")
}
//---except arc/relative paths---
function screenPath(path)
{
var sCTM = path.getCTM()
var svgRoot = path.ownerSVGElement
var segList=path.pathSegList
var segs=segList.numberOfItems
//---change segObj values
for(var k=0;k<segs;k++)
{
var segObj=segList.getItem(k)
if(segObj.x && segObj.y )
{
var mySVGPoint = svgRoot.createSVGPoint();
mySVGPoint.x = segObj.x
mySVGPoint.y = segObj.y
mySVGPointTrans = mySVGPoint.matrixTransform(sCTM)
segObj.x=mySVGPointTrans.x
segObj.y=mySVGPointTrans.y
}
if(segObj.x1 && segObj.y1)
{
var mySVGPoint1 = svgRoot.createSVGPoint();
mySVGPoint1.x = segObj.x1
mySVGPoint1.y = segObj.y1
mySVGPointTrans1 = mySVGPoint1.matrixTransform(sCTM)
segObj.x1=mySVGPointTrans1.x
segObj.y1=mySVGPointTrans1.y
}
if(segObj.x2 && segObj.y2)
{
var mySVGPoint2 = svgRoot.createSVGPoint();
mySVGPoint2.x = segObj.x2
mySVGPoint2.y = segObj.y2
mySVGPointTrans2 = mySVGPoint2.matrixTransform(sCTM)
segObj.x2=mySVGPointTrans2.x
segObj.y2=mySVGPointTrans2.y
}
}
//---force removal of transform--
path.setAttribute("transform","")
path.removeAttribute("transform")
}
//---changes all transformed points to screen 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","")
}
</script>
<script>
document.addEventListener("onload",init(),false)
function init()
{
mySVGValue.value=svgDiv.innerHTML
jsValue.value=myScript.text
}
</script>
</body>
</html>