本文介绍如何将页面加载即执行的圆形进度条动画,改造为仅在用户滚动至该元素进入视口时才启动,通过 intersection observer api 实现高性能、无抖动的懒加载式动画触发。
本文介绍如何将页面加载即执行的圆形进度条动画,改造为仅在用户滚动至该元素进入视口时才启动,通过 intersection observer api 实现高性能、无抖动的懒加载式动画触发。
传统 scroll 事件监听方式(如 window.addEventListener('scroll', ...))虽可检测滚动,但频繁触发易导致性能问题,且需手动计算元素位置、判断是否可见,代码冗余且兼容性差。现代推荐方案是使用 Intersection Observer API —— 浏览器原生支持的轻量级观察者机制,专为“元素是否进入/离开视口”场景设计,无需手动节流,响应高效,兼容性覆盖 Chrome 63+、Firefox 58+、Safari 12.1+ 及 Edge 79+。
以下为完整可运行的优化实现:
<div class="progress-wrapper"> <div class="circular-progress"></div> <div class="value-container">0%</div> </div>
.circular-progress {
width: 150px;
height: 150px;
border-radius: 50%;
background: conic-gradient(#FBDA9D 0deg, #683279 0deg);
position: relative;
}
.value-container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 24px;
font-weight: bold;
color: #333;
}
// 封装进度条动画逻辑
function startProgress(progressBar, valueContainer, endValue = 65, speed = 50) {
let progressValue = 0;
const progress = setInterval(() => {
progressValue++;
valueContainer.textContent = `${progressValue}%`;
progressBar.style.background = `conic-gradient(
#FBDA9D ${progressValue * 3.6}deg,
#683279 ${progressValue * 3.6}deg
)`;
if (progressValue >= endValue) {
clearInterval(progress);
}
}, speed);
}
// 使用 Intersection Observer 触发动画
const progressBar = document.querySelector(".circular-progress");
const valueContainer = document.querySelector(".value-container");
if (progressBar && valueContainer) {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// 元素进入视口:启动动画并停止观察(避免重复触发)
startProgress(progressBar, valueContainer, 65, 50);
observer.unobserve(entry.target);
}
});
},
{
threshold: 0.1 // 当 10% 高度进入视口时即触发
}
);
observer.observe(progressBar); // 观察进度条容器本身(也可观察 wrapper)
}
✅ 关键注意事项:
- 务必检查 DOM 元素是否存在:querySelector 返回 null 时需加判空,否则脚本报错中断;
- 动画仅触发一次:调用 observer.unobserve() 防止同一元素多次进入视口重复执行;
- threshold 灵活设置:0 表示完全进入才触发,0.1 更早响应,1 表示完全可见才启动;
- 兼容性兜底(可选):若需支持 IE,可用 scroll + getBoundingClientRect() 手动实现,但强烈建议优先使用 Intersection Observer;
- CSS 初始化建议:.circular-progress 初始背景设为 conic-gradient(#FBDA9D 0deg, #683279 0deg),避免动画前闪白。
此方案彻底解决了原代码“一进页面就跑”的问题,让交互更符合用户预期——内容可见时才呈现动态效果,既提升性能,又增强视觉叙事节奏。











