【问题标题】:How do I track the position of a moving svg element in relationship to a fixed svg element?如何跟踪移动 svg 元素相对于固定 svg 元素的位置?
【发布时间】:2014-05-07 15:56:48
【问题描述】:

我正在开发一个项目,该项目将 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()函数来跟踪路径的位置?

谢谢, --克里斯托弗

【问题讨论】:

    标签: javascript svg position


    【解决方案1】:

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

    编辑:我在下面包含了一个可以在参考线之间移动矩形的示例。即使 rect 先前已被转换,这也有效。这使用单个 SVG Wrapper。注意:如果您只想对元素进行一次变换,则不必对 bbx、bb 值使用矩阵变换。可以直接使用。

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

    【讨论】:

    • 我需要在我想要跟踪的每个元素周围放置一个 svg 包装器?
    • 您可以拥有一个由您要读取或定位的路径填充的包装器。我将为此答案添加一个示例。给我一个小时左右...
    • 谢谢你,弗朗西斯。这里有很多我还不熟悉的新事物。我会花几天时间仔细研究它,以尝试真正理解它,看看是否可以将类似的东西融入我已经写过的内容中。
    • 弗朗西斯,再次感谢您。这帮助很大。
    • 好的,太好了。祝你的应用好运。
    猜你喜欢
    • 1970-01-01
    • 2012-03-26
    • 1970-01-01
    • 2015-12-21
    • 2011-02-13
    • 2021-01-15
    • 2020-01-15
    • 2012-10-13
    • 1970-01-01
    相关资源
    最近更新 更多