【问题标题】:SVG Matching stroke-dashoffset from two different paths来自两个不同路径的 SVG 匹配 stroke-dashoffset
【发布时间】:2020-10-21 16:25:39
【问题描述】:

我有两条不同的路径,我在其中为 stroke-dashoffset 设置动画,这会产生绘图效果。有两个按钮可以增加/减少 stroke-dashoffset。

我想要实现的是通过匹配在整个进程中垂直对齐的填充路径。这甚至可能吗?

目前在演示中,两条路径的笔划-破折号不匹配,因为锯齿状路径的长度更大。

我希望避免涉及将主路径放在其他两个顶部的解决方案,因为它会摆脱锯齿线上的“绘图”动画外观,并且两条路径都有圆形末端。

const btnAdd = document.querySelector(".btn-add");
const btnSub = document.querySelector(".btn-sub");
const line = document.querySelector(".line");
const jaggedLine = document.querySelector(".jagged-line");
const lineLength = line.getTotalLength();
const jaggedLineLength = jaggedLine.getTotalLength();

line.setAttribute("stroke-dasharray", lineLength);
jaggedLine.setAttribute("stroke-dasharray", jaggedLineLength);
line.setAttribute("stroke-dashoffset", lineLength);
jaggedLine.setAttribute("stroke-dashoffset", jaggedLineLength);

let progress = 0;

const updateSVG = () => {
  line.setAttribute("stroke-dashoffset", lineLength - progress);
  jaggedLine.setAttribute("stroke-dashoffset", jaggedLineLength - progress);
};
btnAdd.addEventListener("click", () => {
  progress++;
  updateSVG();
});
btnSub.addEventListener("click", () => {
  progress--;
  updateSVG();
});
.svg {
  margin-top: 50px;
}
  <button class="btn-add">+</button>
  <button class="btn-sub">-</button>
  <div class="svg">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 73.76 45.715" height="172.781" width="278.7779">
      <g fill="none" stroke="#00aad4" stroke-linecap="round">
        <path
          d="M.8825 28.1368h7.6506l2.6171-10.6905 6.865 25.6202 3.1614-36.3492 3.9609 28.4864 1.1125-6.9395h8.7471l1.2762-7.3971 4.4477 23.966 2.3077-38.0867 1.6134 15.1554h7.5l3.3783 16.805 1.6625-13.5108h15.6946"
          opacity=".165" stroke-width=".965" stroke-linejoin="round" />
        <path d="M.8825.8825h71.995" opacity=".1648" stroke-width=".965" />
        <path class="jagged-line"
          d="M.8825 28.1368h7.6506l2.6171-10.6905 6.865 25.6202 3.1614-36.3492 3.9609 28.4864 1.1125-6.9395h8.7471l1.2762-7.3971 4.4477 23.966 2.3077-38.0867 1.6134 15.1554h7.5l3.3783 16.805 1.6625-13.5108h15.6946"
          stroke-width="1.765" stroke-linejoin="round" />
        <path class="line" d="M.8825.8825h71.995" stroke-width="1.765" />
      </g>
    </svg>
  </div>

【问题讨论】:

  • 在这些路径上合成单个矩形听起来是最简单的方法,尽管圆形线帽会很麻烦......
  • 一个丑陋的解决方案是发送垃圾邮件 getPointAtLength 直到其 x 匹配 progress: jsfiddle.net/o8p5u3za
  • @Kaiido Ugly as in,性能不理想?我认为使用 requestAnimationFrame 而不是 while 循环可以缓解阻塞主线程。到目前为止,您的解决方案是最好的,谢谢:)
  • 丑陋的因为不是很动态。例如,它假设动画只在 x 轴上进行,如果有一天你决定旋转它,整个代码就会中断。性能方面应该没问题。

标签: javascript html css svg


【解决方案1】:

有一个 SVG 属性 pathLength 允许我们设置路径长度。

pathLength 属性允许作者指定路径的总长度,以用户单位为单位。然后使用该值来校准浏览器的距离计算与作者的距离计算,通过使用比率 pathLength/(路径长度的计算值)缩放所有距离计算。

这会影响路径的实际渲染长度;包括文本路径、动画路径和各种笔画操作。基本上,所有需要路径长度的计算。例如,stroke-dasharray 将假定路径的起点为 0,终点为 pathLength 属性中定义的值。

MDN

如果我们给这两个动画设置相同的pathLength,就变得简单了。

.svg {
  display: inline-block;
  margin: 1em;
}

.line,
.jagged-line {
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  animation: dash 5s linear alternate infinite;
}

@keyframes dash {
  from {
    stroke-dashoffset: 100;
  }
  to {
    stroke-dashoffset: 0;
  }
}
<div class="svg">
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 73.76 45.715" height="172.781" width="278.7779">
      <g fill="none" stroke="#00aad4" stroke-linecap="round">
        <path
          d="M.8825 28.1368h7.6506l2.6171-10.6905 6.865 25.6202 3.1614-36.3492 3.9609 28.4864 1.1125-6.9395h8.7471l1.2762-7.3971 4.4477 23.966 2.3077-38.0867 1.6134 15.1554h7.5l3.3783 16.805 1.6625-13.5108h15.6946"
          opacity=".165" stroke-width=".965" stroke-linejoin="round" />
        <path d="M.8825.8825h71.995" opacity=".1648" stroke-width=".965" />
        <path class="jagged-line"
          d="M.8825 28.1368h7.6506l2.6171-10.6905 6.865 25.6202 3.1614-36.3492 3.9609 28.4864 1.1125-6.9395h8.7471l1.2762-7.3971 4.4477 23.966 2.3077-38.0867 1.6134 15.1554h7.5l3.3783 16.805 1.6625-13.5108h15.6946"
          stroke-width="1.765" stroke-linejoin="round" pathLength="100"/>
        <path class="line" d="M.8825.8825h71.995" stroke-width="1.765" pathLength="100"/>
      </g>
    </svg>
</div>

【讨论】:

  • 如此接近,但在进程的某些部分不一致。我需要它们在整个过程中长度相等。
  • 不太清楚你的意思......路径的长度相同。我怀疑您的意思是您希望填充的部分垂直对齐,这是另一个问题,而且要复杂得多,因为动画不是线性的。
  • 对不起,我不应该说等长。你措辞完美,我希望填充的路径在整个进程中垂直对齐。到目前为止,@Kaiido 能够使用 getPointAtLength 属性解决我的问题,即使它使用 while 循环来不断检查它。感谢您花时间帮助我:)
  • 您可以将直线分成与锯齿线相同数量的路径段,然后为每个直线段赋予与其孪生线锯齿线相同的 pathLength。
  • @RobertLongson 所以直线必须与锯齿线具有相同数量的节点?或者实际上分解成单独的路径元素。这是一个演示,显示了两条不同的直线,一条有两个节点,另一条的节点数量与锯齿线相同,但没有区别。 jsfiddle.net/Lishipu/jwoLr1h9/8
猜你喜欢
  • 2021-09-08
  • 2018-04-17
  • 1970-01-01
  • 1970-01-01
  • 2015-08-21
  • 2018-05-14
  • 2023-03-27
  • 2016-07-26
  • 2012-12-08
相关资源
最近更新 更多