【问题标题】:Get point's y coordinate on svg path在 svg 路径上获取点的 y 坐标
【发布时间】:2014-05-03 05:52:50
【问题描述】:

我想我需要添加一些解释,我想问这个问题,因为太短的问题没有质量标准......有趣......

那么,问题来了: 如何在特定的“x”坐标处获取 svg 路径上点的“y”坐​​标?

【问题讨论】:

    标签: svg path coordinates point


    【解决方案1】:

    这并不简单,因为一条路径可能有多个具有指定x 坐标的点。

    SVG DOM 中没有内置函数来执行此操作。一种解决方案是沿着路径分段并自己计算。

    另外,SVGPathElement 上有一个名为 getPointAtLength(len) 的内置函数。您沿路径传递一个长度,它将返回该点的 x,y 坐标。您可以沿着路径长度计算 x 坐标与您想要的x 交叉的位置。您可以从SVGPathElement.getTotalLength() 函数中获取路径长度。这有点麻烦,您必须小心不要错过x 附近曲线弯曲的点。但它应该可以工作。

    See here for more information on these functions.

    【讨论】:

    • 我之前想过沿着路径长度走,但是因为多点而试图避免它。虽然最后我最终采用了这种方法,但在我的情况下结果很好。
    • 我刚刚将它添加到我的代码中,但速度非常慢。这显然在很大程度上取决于步长 - 我玩弄了它并将它放在一个点以下它变得太不精确,但它仍然将我的 FPS 减少了一半。还有其他想法吗?我发现了这个,这有点酷,但有点矫枉过正:bl.ocks.org/mbostock/8027637
    • 您指向的代码也使用getPointAtLength()。听起来您可能正在使用固定的步长。您应该做的是使用粗略的步骤,直到您在搜索 x 的任一侧找到 x 点。然后根据您的搜索 x 在该范围内的位置估计下一个长度。您只需猜测几下即可获得准确的容差。
    • 我认为在给定容差范围内对所需 X 点进行二分搜索可能会更好
    【解决方案2】:

    我正在解决类似的问题,Paul 的回答对我很有帮助。

    为了进一步说明@Paul LeBeau 的回答,这里有一个小演示:

    let path = document.getElementById("path");
    let svg = document.getElementById("svg");
    
    // The first important function getTotalLength
    let totalLength = path.getTotalLength();
    let intersections = 27;
    
    for(var i = 0; i <= intersections; i ++){
      let distance = i * 1/intersections * totalLength;
      
      // The second important function getPointAtLength
      let point = path.getPointAtLength(distance);
      addCircleToSVG(point.x, point.y);
      addTextToSVG(point.x, point.y);
    }
    
    function addCircleToSVG(x, y){
      let circle = document.createElementNS("http://www.w3.org/2000/svg",'circle');
      circle.setAttribute("cx", x);
      circle.setAttribute("cy", y);
      circle.setAttribute("r", "5");
      circle.setAttribute("fill", "#8888ff");
      svg.appendChild(circle);
    }
    
    function addTextToSVG(x, y){
      let text = document.createElementNS("http://www.w3.org/2000/svg",'text');
      text.setAttribute("x", x + 10);
      text.setAttribute("y", y);
      text.setAttribute("fill", "orange");
      text.innerHTML = Math.round(y);
      svg.appendChild(text);
    }
    svg{
      width:auto;
      height: auto;
    }
    <svg id="svg" viewBox="0 0 1184.25 455.99">
      <path id="path" class="st0" d="M0.18,455.53c0,0,73-311,128-311s86,276,122,287s52-22,112-25s114,16,146,18s34,20,64,16s45-144,93-133
    	s55-21,88-17s58,151,85,149s103-13,128-8s48-21,85-19c37,2,133,43,133,43" fill="#666666"/>
    </svg>

    【讨论】:

      【解决方案3】:

      如果您知道路径的所有点,我相信比单步执行路径更高效的解决方案可能是搜索路径的 d 属性以查找您正在寻找的特定 x 坐标。然后使用正则表达式捕获 y 坐标。正则表达式可以这样使用:

      const regex = new RegExp(`${x} ((\d*.\d*))`)
      const match = regex.exec(d)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-12
        • 2020-04-22
        • 2022-01-13
        • 1970-01-01
        • 2011-09-25
        • 2011-02-14
        • 2015-05-05
        • 2019-08-01
        相关资源
        最近更新 更多