SVG - 获得未转换的积分?

时间:2014-04-07 19:21:56

标签: svg transformation

说我有以下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

1 个答案:

答案 0 :(得分:2)

以下是转换后返回屏幕点的示例:polygon,path,polyline。路径示例不起作用或弧。此外,在某些情况下,相对点可能不会返回。这使用getCTMmatrixTransform。可以创建一个数组来“记住”各个时间线上的点。

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