简体   繁体   English

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

[英]How do I track the position of a moving svg element in relationship to a fixed svg element?

I am working on a project that moves elements of an svg file up and down across a horizontal line. 我正在做一个项目,该项目将svg文件的元素在水平线上上下移动。 I want to track the position of the moving element in relation to the fixed line. 我想跟踪移动元素相对于固定线的位置。 Both elements are within the same svg. 两个元素都在同一个svg中。 I tried using 我尝试使用

getBoundingClientRect().top

However, this does not provide a good solution as the coordinates produced by the getBoundingClientRect() function change based on the size, position, and zoom, of the viewport. 但是,由于由getBoundingClientRect()函数产生的坐标根据视口的大小,位置和缩放而变化,因此,这不是一个好的解决方案。 It is not the same for every device in every situation. 在每种情况下,每种设备的情况都不相同。 I need to be able to know when a specific path is a certain distance above or below a fixed line. 我需要能够知道一条特定路径何时位于固定线以上或以下。 I'm using setAttribute('transform','translate()) on the containing group to move a group of objects in my project. 我在包含组上使用setAttribute('transform','translate())在我的项目中移动一组对象。 I need to know the position of an individual object within my group in relation to a fixed line not in my group. 我需要知道单个对象在组中相对于不在组中的固定线的位置。

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

Is there a way to track the position of the path without using the getBoundingClientRect() function? 有没有一种方法可以在不使用getBoundingClientRect()函数的情况下跟踪路径的位置?

Thanks, --christopher 谢谢--christopher

Try placing your path in an svg 'wrapper/empty' element. 尝试将路径放置在svg“包装器/空”元素中。 Then use getBBox() for the wrapper. 然后将getBBox()用于包装器。 This will provide x,y values used to set/read the path's translations. 这将提供用于设置/读取路径转换的x,y值。

EDIT: I have included an example below that can move rects between reference lines. 编辑:我下面包含一个示例,可以在参考线之间移动矩形。 This works even when the rect has been previously transformed. 即使rect已预先转换,这也可以工作。 This uses a single SVG Wrapper. 这使用单个SVG包装器。 Note: If you are only going to transform your element a single time, then you do not have to use the matrix transform on the bbx, bby values. 注意:如果只打算一次变换元素,则不必在bbx,bby值上使用矩阵变换。 they can be used directly. 它们可以直接使用。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM