如何跟踪移动的svg元素相对于固定svg元素的位置?

时间:2014-05-07 15:56:48

标签: javascript svg position

我正在开发一个项目,可以在水平线上上下移动svg文件的元素。我想跟踪移动元素相对于固定线的位置。这两个元素都在同一个svg中。我尝试使用

getBoundingClientRect().top

但是,由于getBoundingClientRect()函数生成的坐标会根据视口的大小,位置和缩放而发生变化,因此无法提供良好的解决方案。在每种情况下,每台设备都不一样。我需要能够知道特定路径何时在固定线的上方或下方一定距离。我在包含组上使用setAttribute('transform','translate())来移动项目中的一组对象。我需要知道我的组中单个对象相对于不在我组中的固定行的位置。

<svg version="1.1" id="ex1-3rds-quarter-s" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
 y="0px" width="323.333px" height="55.333px" viewBox="0 0 323.333 55.333" enable-background="new 0 0 323.333 55.333"
 xml:space="preserve">
  <g id="ledgerlines">
    <line id="MidCLine1" fill="none" stroke="#000000" stroke-width="0.75" stroke-miterlimit="10" x1="48.09" y1="41.694" x2="57.924" y2="41.694"/>
  </g>
  <g id="note1">
    <path class="root" d="M54.113,38.945c1.116,0,2.172,0.578,2.172,1.813c0,1.435-1.116,2.411-2.052,2.969c-0.717,0.418-1.514,0.717-2.331,0.717
            c-1.116,0-2.172-0.578-2.172-1.813c0-1.435,1.116-2.411,2.052-2.969C52.499,39.244,53.296,38.945,54.113,38.945z"/>
    <path d="M54.113,33.963c1.116,0,2.172,0.578,2.172,1.813c0,1.435-1.116,2.411-2.052,2.969c-0.717,0.418-1.514,0.717-2.331,0.717
            c-1.116,0-2.172-0.578-2.172-1.813c0-1.435,1.116-2.411,2.052-2.969C52.499,34.262,53.296,33.963,54.113,33.963z"/>
  </g>
</svg>

有没有办法在不使用getBoundingClientRect()函数的情况下跟踪路径的位置?

谢谢, --christopher

1 个答案:

答案 0 :(得分:1)

尝试将路径放在svg'wrapper / empty'元素中。然后使用getBBox()作为包装器。这将提供用于设置/读取路径翻译的x,y值。

编辑:我在下面列出了一个可以在参考线之间移动rects的示例。即使先前已经转换了矩形,这也可以工作。这使用单个SVG Wrapper。注意:如果您只是一次转换元素,那么您不必对bbx,bby值使用矩阵变换。它们可以直接使用。

<!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
        <title>SVG Wrapper</title>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">
        </head>
        <body style='font-family:arial'>
            <center>
            <h4>SVG Wrapper</h4>
            <div style='width:90%;background-color:gainsboro;text-align:justify;padding:10px;border-radius:6px;'>
           Translate rects to line via SVG Wrapper. Can translate between lines
            </div>
            <div id="svgDiv" style='background-color:gainsboro;width:400px;height:400px;'>
<svg id="mySVG" width="400" height="400">
<line id=refLine1 stroke='blue' stroke-width='2' x1=20 y1=40 x2=380 y2=40 />
<line id=refLine2 stroke='maroon' stroke-width='2' x1=20 y1=100 x2=380 y2=100 />
<g id=rectG>
<rect id=redRect fill=red x=60 y=200 width=100 height=50 />
<rect id=greenRect fill=lime x=260 y=320 width=100 height=50 />
</g>
<svg id=Wrapper />
</svg>
            </div>
<center>
<button onClick=moveToLine(refLine1,redRect)>Move Red Rect to <span style=color:blue>Line 1</span></button>
<button onClick=moveToLine(refLine1,greenRect)>Move Green Rect to <span style=color:blue>Line 1</span></button>
<br />
<button onClick=moveToLine(refLine2,redRect)>Move Red Rect to <span style=color:maroon>Line 2</span></button>
<button onClick=moveToLine(refLine2,greenRect)>Move Green Rect to <span style=color:maroon>Line 2</span></button>
</center>
            <br />SVG Source:<br />
            <textarea id=svgSourceValue style='font-size:110%;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:5px;position:absolute;top:5px;left:5px;background-color:gainsboro;'>OK in:IE11/CH32/FF28<br /></div>
<script id=myScript>
function moveToLine(refLine,rect)
{
    //---move rect to this location at line---
    var targetY=refLine.y1.baseVal.value
    var targetX=rect.x.baseVal.value
    Wrapper.appendChild(rect)
    var bb=Wrapper.getBBox()
    //---return rect to its <g>---
    rectG.appendChild(rect)
    var bbx=bb.x
    var bby=bb.y

    //---bind wrapper x,y to rect's current transform--
    var pnt = mySVG.createSVGPoint();
    pnt.x = bbx;
    pnt.y = bby;
    var sCTM = rect.getCTM();
    PNT = pnt.matrixTransform(sCTM.inverse());
    //---translate rect's x,y to target---
    var transX=targetX-PNT.x
    var transY=targetY-PNT.y

    rect.setAttribute("transform","translate("+transX+" "+transY+")")

    svgSourceValue.value=svgDiv.innerHTML
}

</script>
            <script>
            document.addEventListener("onload",init(),false)
            function init()
            {
                svgSourceValue.value=svgDiv.innerHTML
                jsValue.value=myScript.text
            }
            </script>
        </body>
    </html>