Django模板中JS滚动计数动画失效问题排查求助
滚动触发计数动画失效的修复
问题代码
HTML(Django模板)
<section class="numc"> <div class="nums"> <div class="num" data-goal="50">0</div> <div class="num" data-goal="60">0</div> <div class="num" data-goal="100">0</div> </div> </section> <script src="{% static 'javascript/js.js' %}"></script>
原JS代码
let nums = document.querySelectorAll(".nums .num"); let section = document.querySelector(".numc"); window.onscroll = function () { if (window.scrollY >= section.offsetTop) { nums.forEach((num) => startCount(num)); } }; function startCount(el) { let goal = el.dataset.goal; let count = setInterval(() => { el.textcontent++; if (el.textcontent == goal) { clearInterval(count); } }, 10); }
错误分析与修复要点
- 属性名拼写错误:
textcontent应为DOM标准驼峰属性名textContent,拼写错误会导致无法修改元素文本。 - 滚动重复触发:滚动事件会持续触发,多次调用
startCount会导致多个计数器同时运行,数字跳变。需添加标记确保计数仅执行一次。 - 类型不匹配:
dataset.goal返回字符串,直接与数字比较会引发逻辑错误,需转为数字类型。 - 视口判断不准确:仅用
scrollY >= section.offsetTop会在元素顶部刚触达页面顶部就触发,应判断元素是否进入视口(至少部分可见)。
修正后的JS代码
let nums = document.querySelectorAll(".nums .num"); let section = document.querySelector(".numc"); let hasTriggered = false; // 标记计数是否已触发 // 判断元素是否进入视口 function isElementInViewport(el) { const rect = el.getBoundingClientRect(); return rect.top <= window.innerHeight && rect.bottom >= 0; } window.onscroll = function () { if (isElementInViewport(section) && !hasTriggered) { hasTriggered = true; nums.forEach((num) => startCount(num)); } }; function startCount(el) { let current = 0; const goal = parseInt(el.dataset.goal, 10); // 转为整数类型 const increment = Math.ceil(goal / 100); // 统一计数步长,让动画更协调 const count = setInterval(() => { current += increment; // 到达目标值时停止计数 if (current >= goal) { current = goal; clearInterval(count); } el.textContent = current; // 修正属性名 }, 20); // 调整间隔,优化动画流畅度 }
额外优化说明
- 新增
hasTriggered变量,避免滚动时重复触发计数逻辑。 - 使用
getBoundingClientRect()实现更精准的视口判断,适配不同屏幕尺寸。 - 通过计算
increment步长,让不同目标值的计数速度保持一致,提升视觉体验。
内容的提问来源于stack exchange,提问作者Taha Alsaity
相关产品推荐
相关产品推荐

