Intersection Observer统计计数器重复进入视口时异常问题求助
Intersection Observer统计计数器重复进入视口时异常问题求助
嘿,刚上手Intersection Observer遇到这种问题太正常了!我帮你分析下问题出在哪,再给你调整后的解决方案:
问题根源
你现在的代码有两个核心问题:
- 没有标记已完成动画的元素:每次元素滚回视口时,都会重新触发计数器逻辑,甚至可能同时存在多个定时器一起修改数值,导致数值直接冲过目标值停不下来。
- 只观察了第一个统计容器:你代码里只调用了
observer.observe(statContainer[0]),另外两个容器根本没被监听,不过这是次要问题,先解决重复触发的核心问题。
解决方案
我们可以给每个完成动画的容器加一个自定义属性来标记状态,确保每个计数器只运行一次;同时调整监听逻辑,让所有容器都被观察到。
修改后的JavaScript代码:
let statContainer = document.getElementsByClassName("stat-container"); const observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (entry.isIntersecting) { const container = entry.target; // 检查是否已经执行过动画,避免重复触发 if (container.dataset.animated === "true") return; let circularProgress = container.querySelector(".circular-progress"), progressValue = container.querySelector(".progress-value"); let progressStartValue = 0, progressEndValue = parseInt(progressValue.textContent.trim()), // 转成数字并去除空格 speed = 10; let progress = setInterval(() => { progressStartValue++; progressValue.textContent = `${progressStartValue}%`; circularProgress.style.background = `conic-gradient(#099bf0, #7cbf3d,#00b3cf, #1f58f2, #5618d4 ${progressStartValue * 3.6}deg, #EAEAEC 0deg)`; if (progressStartValue === progressEndValue) { clearInterval(progress); // 标记该容器已完成动画 container.dataset.animated = "true"; } }, speed); } }); }); // 遍历所有统计容器,添加监听 Array.from(statContainer).forEach(container => { observer.observe(container); });
关键修改点说明
- 添加状态标记:用
dataset.animated属性记录容器是否已经执行过动画,每次触发交集时先判断这个状态,已完成就直接跳过。 - 处理目标值格式:把
progressEndValue转成整数并去除空格,避免因为原文本里的换行/空格导致数值判断出错。 - 监听所有容器:用
Array.from把HTMLCollection转成数组,遍历每个容器添加监听,确保所有统计项都能触发逻辑。 - 绑定到当前entry的target:直接用
entry.target获取当前交集的容器,不用再循环所有容器,避免每次触发都操作所有统计项。
这样修改后,每个统计计数器只会在第一次进入视口时运行一次,之后再滚回视口也不会重复触发,数值就不会出现超标的情况啦。
备注:内容来源于stack exchange,提问作者rnkwill
相关产品推荐
相关产品推荐

