在SVG路径上获取点的y坐标

6

我猜我需要添加一些解释,我想问这个问题,因为太短的问题不符合标准......有趣...

所以,这是问题: 如何在特定的“x”坐标上获取svg路径上点的“y”坐标?

3个回答

13

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

SVG DOM 中没有内置的函数可以解决此问题。一种解决方法是沿着路径段进行步进并自己计算数学公式。

或者,SVGPathElement 上有一个内置函数叫做 getPointAtLength(len)。您可以传入路径上的长度,并返回该点的 x、y 坐标。您可以沿着路径长度前进,并计算出 x 坐标与期望的 x 交叉的位置。您可以使用 SVGPathElement.getTotalLength() 函数获取路径长度。这有点笨拙,您必须小心不要错过曲线弯曲接近您的 x 的点。但这应该可行。

在此处查看有关这些功能的更多信息。


我之前考虑过沿着路径长度进行步进,但因为存在多个点而试图避免。尽管最终我采用了这种方法,在我的情况下证明它能够很好地工作。 - El Kopyto
我刚把这个加到我的代码里,但它运行得非常慢。显然这取决于步长 - 我试着调整了一下,将其设置为一个比较精确的点以下,但仍然会使我的FPS减半。 还有其他的想法吗?我找到了这个,看起来很酷,但有点过头了:http://bl.ocks.org/mbostock/8027637 - Micha Schwab
1
你指出的那段代码也使用了 getPointAtLength()。听起来你可能正在使用固定步长。你应该使用粗略的步长,直到找到搜索 x 两侧的 x 点。然后根据搜索 x 落在该范围内的位置估算下一个长度。只需要几次猜测就可以达到准确容差范围内。 - Paul LeBeau
我认为最好使用二分查找算法,在给定容差范围内搜索所需的X点。 - BallpointBen

1

我曾经遇到类似的问题,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>


0
如果您知道路径的所有点,我相信比遍历路径更高效的解决方案是搜索路径的d属性,以查找您要查找的特定x坐标。然后使用正则表达式捕获y坐标。可以像这样使用正则表达式:
const regex = new RegExp(`${x} ((\d*.\d*))`)
const match = regex.exec(d)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接