You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JavaScript中高效获取SVG路径到指定Y坐标的长度

优化SVG路径指定Y坐标对应长度的获取性能

我有一条复杂的SVG路径,已知目标Y坐标,需要获取路径从起点到该Y坐标位置的总长度。
示例

我用二分查找定位对应Y坐标的路径线段,代码如下:

function binarySearchLengthByYCoord(path, yCoord) {
    const pathTotalLength = +path.getTotalLength();
    let low = 0;
    let high = pathTotalLength;
    let result = 0;

    while (low <= high) {
        const mid = Math.floor((low + high) / 2);
        const point = path.getPointAtLength(mid);

        if (point.y < yCoord) {
            low = mid + 1;
            result = mid;
        } else {
            high = mid - 1;
        }
    }
    return pathTotalLength - result;
}

这段代码能正常工作,但每次滚动事件触发都要调用,在低端设备和手机上性能问题明显。我需要保持现有动画效果的同时,实现更高效的代码。完整实现代码如下:

JavaScript代码

scrollLineAnimation();
function scrollLineAnimation() {
  const decorParent = document.querySelector("[data-line-animation]"),
    lines = decorParent.querySelectorAll("svg");

  if (lines.length) {
    const line = lines[0],
      path = line.getElementsByTagName("path")[0],
      pathTotalLength = +path.getTotalLength(),
      lastYCoord = path.getPointAtLength(pathTotalLength).y,
      offsetHeight = decorParent.dataset.lineAnimation
        ? decorParent.dataset.lineAnimation
        : 0.8;

    line.style.strokeDasharray = pathTotalLength;
    line.style.strokeDashoffset = pathTotalLength;
    line.style.display = "block";

    let position = 0;
    let prcPostion = 0;

    updateStrokeDashoffset();
    window.addEventListener("scroll", updateStrokeDashoffset);
    window.addEventListener("resize", updateStrokeDashoffset);

    // 获取Y坐标并查找路径线段的函数
    function updateStrokeDashoffset() {
      const scrollPosition = window.scrollY,
        windowHeight = window.innerHeight,
        svgHeight = line.getBoundingClientRect().height,
        yCoord =
          (scrollPosition + windowHeight * offsetHeight) *
          (lastYCoord / svgHeight),
        newStrokeDashoffsetValue = binarySearchLengthByYCoord(path, yCoord);

      prcPostion = (newStrokeDashoffsetValue / pathTotalLength) * 100;
    }

    // 平滑动画函数
    function setStrokeDashoffset() {
      let dist = prcPostion - position;
      position = position + (dist * 70) / 1000;

      line.style.strokeDashoffset = Math.round(
        (position * pathTotalLength) / 100
      );

      requestAnimationFrame(setStrokeDashoffset);
    }

    requestAnimationFrame(setStrokeDashoffset);
  }

  function binarySearchLengthByYCoord(path, yCoord) {
    const pathTotalLength = +path.getTotalLength();
    let low = 0;
    let high = pathTotalLength;
    let result = 0;

    while (low <= high) {
      const mid = Math.floor((low + high) / 2);
      const point = path.getPointAtLength(mid);

      if (point.y < yCoord) {
        low = mid + 1;
        result = mid;
      } else {
        high = mid - 1;
      }
    }

    return pathTotalLength - result;
  }
}

CSS代码

body {
  max-width: 100%;
  position: relative;
  padding: 0;
  margin: 0;
  min-height: 6000px;
}
.decor {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  max-width: 1440px;
}

.decor svg {
  position: absolute;
  display: none;
  left: 0;
  top: 0;
  width: 100%;
  height: auto;
  min-height: 100%;
}

HTML代码

<div data-line-animation="0.8" class="decor">
  <svg preserveAspectRatio="none" width="1440" height="5141" viewBox="0 0 1440 5141" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path d="M886.805 0.0743205C986.888 -1.4439 1187.91 19.063 1065.22 176.635C911.848 373.6 1455.21 527.592 1367.57 373.601C1279.93 219.61 613.874 395.088 1152.86 656.514C1584.04 865.655 736.569 920.328 258.934 921.522C91.767 929.283 -164.804 1007.13 146.247 1256.43C535.061 1568.06 1238.55 1700.59 1195.7 1890.43C1152.86 2080.27 -384.754 2905.95 146.247 2905.95C1314.52 2905.95 250.102 3383.41 709.046 3545.41C849.007 3594.81 1440.94 3511.17 1410.12 3824.66C1352.7 4408.75 -60.5479 4131.44 95.6015 4451.98C290.788 4852.65 1410.12 5002.4 1440 5140" stroke="#2BB32A" stroke-width="1.5" stroke-linecap="square" />
  </svg>
</div>

请问是否有更高效的方法来获取SVG路径到指定Y坐标的长度?


内容的提问来源于stack exchange,提问作者Ci4ENb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 21:55:54