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

实现SVG路径动画随页面滚动触发(无需jQuery)

实现SVG路径滚动触发动画(原生JS)

问题

当前SVG路径动画在页面加载时自动完成,需要改为滚动到SVG所在区域时才触发动画,要求用原生JavaScript实现,不引入任何额外库。

解决步骤

1. 调整CSS结构

先移除原来直接绑定在.st0、.st1上的自动动画,把动画逻辑放到单独的类中,只有当元素添加这个类时才会启动动画:

/* 基础样式保留,移除自动动画 */
.st0, .st1{
  fill:none;
  stroke:#000000;
  stroke-miterlimit:10;
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
}

/* 动画类,需要时才添加 */
.animate-path {
  -webkit-animation: draw1 4s linear forwards;
  animation: draw1 4s linear forwards;
}

/* 动画关键帧保留 */
@-webkit-keyframes draw1{
  to {stroke-dashoffset: 0;}
}
@keyframes draw1{
  to {stroke-dashoffset: 0;}
}
@-webkit-keyframes draw2{
  to {stroke-dashoffset: 0;}
}
@keyframes draw2{
  to {stroke-dashoffset: 0;}
}

2. 添加原生JavaScript监听逻辑

这段代码监听页面滚动,判断SVG是否进入视口,一旦进入就给所有路径添加动画类,且只执行一次:

// 获取SVG元素
const svgElement = document.querySelector('svg');
// 获取所有需要动画的路径元素
const pathElements = document.querySelectorAll('.st0, .st1');
// 标记动画是否已触发
let animationTriggered = false;

// 判断元素是否在视口内的函数
function isInViewport(element) {
  const rect = element.getBoundingClientRect();
  return (
    rect.top <= window.innerHeight &&
    rect.bottom >= 0
  );
}

// 滚动监听函数
function checkScroll() {
  if (!animationTriggered && isInViewport(svgElement)) {
    // 给所有路径添加动画类
    pathElements.forEach(el => el.classList.add('animate-path'));
    animationTriggered = true;
    // 动画触发后移除监听,优化性能
    window.removeEventListener('scroll', checkScroll);
  }
}

// 初始化监听
window.addEventListener('scroll', checkScroll);
// 页面加载时先检查一次,避免SVG一开始就在视口内的情况
checkScroll();

3. 完整HTML结构

保留原SVG代码,确保路径类仍为.st0和.st1即可:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 1514.85 819.06" style="enable-background:new 0 0 1514.85 819.06;" xml:space="preserve" >
<style type="text/css">
    .st0{fill:none;stroke:#58595B;stroke-width:2;stroke-miterlimit:10;}
    .st1{fill:none;stroke:#7F8183;stroke-width:2;stroke-miterlimit:10;}
    .st2{fill:#7E8183;}
    .st3{font-family:'Tahoma';}
    .st4{font-size:27px;}
    .st5{fill:#7E8183;stroke:#7E8183;stroke-width:0.09;stroke-miterlimit:10;}
    .st6{fill:#FFFFFF;}
    .st7{fill:none;stroke:#7E8183;stroke-width:2;stroke-miterlimit:10;}
    .st8{fill:#7E8183;stroke:#FFFFFF;stroke-miterlimit:10;}
    .st9{fill:#7E8183;stroke:#FFFFFF;stroke-width:1.6;stroke-miterlimit:10;}
    .st10{fill:#7E8183;stroke:#FFFFFF;stroke-width:0.2174;stroke-miterlimit:10;}
</style>
<g id="Layer_1">
    <polyline class="st0" points="567.16,290.57 402.56,290.57 402.56,193.38  "/>
</g>
<g id="Layer_2">
    <polyline class="st0" points="567.16,373.55 137.02,373.55 137.02,193.38  "/>
</g>
<g id="Layer_3">
    <polyline class="st0" points="567.16,455.77 139.01,455.77 139.01,636.41  "/>
</g>
<g id="Layer_4">
    <polyline class="st0" points="567.16,539.21 402.56,539.21 402.56,636.41  "/>
</g>
<g id="Layer_5">
    <polyline class="st1" points="991.61,290.57 1156.21,290.57 1156.21,193.38  "/>
</g>
<g id="Layer_6">
    <polyline class="st1" points="991.61,373.55 1419.66,373.55 1419.66,193.38  "/>
</g>
<g id="Layer_7">
    <polyline class="st1" points="991.61,455.77 1419.66,455.77 1419.66,636.41  "/>
</g>
<g id="Layer_8">
    <polyline class="st1" points="991.61,539.21 1156.21,539.21 1156.21,636.41  "/>
</g>

</svg>

说明

  • 动画只会触发一次,避免滚动时重复执行
  • 页面加载时会先检查一次,如果SVG一开始就在视口内,会直接启动动画
  • 用getBoundingClientRect()判断元素是否在视口,是原生JS的可靠方法
  • 动画触发后移除滚动监听,减少性能消耗

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 09:48:12