如何实现jQuery进度条滚动到视口时触发动画且仅播放一次
实现方案
直接用原生Intersection Observer实现即可,性能比老的绑定scroll事件手动算偏移的方案好很多,不会出现滚动卡顿,也没有兼容问题,完全满足你的需求。
第一步:补全基础样式
先给进度条设置初始宽度为0,避免页面加载后直接执行动画:
.animated-progress span { width: 0; /* 你原本写的进度条其他样式(高度、背景色、圆角之类)全部保留即可 */ }
第二步:替换原有JS逻辑
首先给你要作为触发锚点的最底部「Copper」项加一个自定义类,比如progress-trigger,方便JS选中。
然后把你原本页面加载就直接跑动画的JS,替换成下面的代码:
// 加锁防止动画重复触发 let hasAnimated = false; const progressObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { // 锚点元素进入视口、且动画没执行过的时候才启动 if (entry.isIntersecting && !hasAnimated) { hasAnimated = true; // 遍历执行所有进度条动画 $(".animated-progress span").each(function () { $(this).animate({ width: `${$(this).attr("data-progress")}%` }, 2000); }); // 触发完直接销毁监听,后续滚动不会再重复执行 progressObserver.disconnect(); } }) }, { // 触发阈值:0表示元素刚进入视口(露出1px)就触发,改成1就是元素完全露出视口才触发,可按需调整 threshold: 0 }) // 绑定监听的锚点元素 progressObserver.observe(document.querySelector(".progress-trigger"))
说明
你之前整合旧帖子代码失效,基本都是老方案本身的问题:scroll事件高频触发容易出现计算逻辑bug,还要处理各种偏移值兼容,手动写很容易出问题。上面的方案是浏览器原生支持的监听方案,不需要手动计算滚动高度、元素位置,稳定性高很多。
方案完全匹配你的补充要求:
- 动画仅触发一次:通过变量锁+触发后销毁监听双重保障,动画跑完后进度条会停在最终状态,不会重复执行也不会重置
- 触发时机精准:只要给最底部的Copper项加好
progress-trigger类,就会在它进入视口时启动动画,阈值参数可以根据你想要的触发时机自行调整。
内容的提问来源于stack exchange,提问作者neilwhitedesign
相关产品推荐
相关产品推荐

