滚动触发数字计数器回落问题求助:期望仅递增后停止
Hey,我帮你找到了问题所在!你的数字计数器滚动到可见区域后跑到85又回落,核心是一个低级拼写错误在搞鬼,还有几个小细节可以优化,下面给你讲清楚:
解决滚动触发数字计数器重复回落的问题
问题核心原因
你在first_num_count函数里,把变量isResizeble_2拼写成了isRezeble_2!这就导致这个用来阻止重复执行的标识永远不会被设为true,每次滚动触发first_num_count时,都会重新启动数字动画——jQuery的animate是队列执行的,前一次动画刚到85,后一次又从0开始,看起来就像回落了。
另外还有个小问题:滚动事件会频繁触发,虽然你加了isResizeble_1,但用节流函数优化一下会更稳妥。
修复方案
- 修正拼写错误:把
isRezeble_2 = true改成isResizeble_2 = true,这是最关键的一步; - 优化动画逻辑:提前保存目标数字,避免动画过程中获取到变化的文本值;把标识锁定放在动画完成回调里,确保动画结束后才不再执行;
- 滚动事件节流:减少滚动时的函数触发频率,提升页面性能。
修正后的完整代码
<!DOCTYPE html> <html> <head> <script src="https://code.jquery.com/jquery-3.4.1.js"></script> <style> body{ height: 900px; } .number-persent{ margin-top: 600px; display: flex; } </style> </head> <body> <div class="number-persent"> <p id="count-num">85</p> <p id="persent">%</p> </div> <script> // 百分比计数器 var isResizeble_1 = false; var isResizeble_2 = false; function first_num_count(){ if(!isResizeble_2) { // 提前保存目标数值,避免动画过程中text值变化导致异常 const targetNum = parseInt($('#count-num').text()); $('#count-num') .prop('Counter', 0) .animate({ Counter: targetNum },{ duration: 2000, easing: 'swing', step: function(now){ $(this).text(Math.ceil(now)); }, complete: function() { // 动画完成后再锁定,确保不会中途重复触发 isResizeble_2 = true; } }); } } // 触发元素 const firstPersent = document.querySelector('#persent'); const Visible = function (target) { // 获取元素位置 const targetPosition = { top: window.pageYOffset + target.getBoundingClientRect().top, left: window.pageXOffset + target.getBoundingClientRect().left, right: window.pageXOffset + target.getBoundingClientRect().right, bottom: window.pageYOffset + target.getBoundingClientRect().bottom }; // 获取窗口位置 const windowPosition = { top: window.pageYOffset, left: window.pageXOffset, right: window.pageXOffset + document.documentElement.clientWidth, bottom: window.pageYOffset + document.documentElement.clientHeight }; if (targetPosition.bottom > windowPosition.top && targetPosition.top < windowPosition.bottom && targetPosition.right > windowPosition.left && targetPosition.left < windowPosition.right) { // 元素可见时仅执行一次计数 if(!isResizeble_1) { first_num_count(); isResizeble_1 = true; } } }; // 节流函数:减少滚动事件触发频率 function throttle(func, delay = 100) { let timer = null; return function() { if (!timer) { timer = setTimeout(() => { func.apply(this, arguments); timer = null; }, delay); } } } // 绑定节流后的滚动事件 window.addEventListener('scroll', throttle(() => Visible(firstPersent))); </script> </body> </html>
额外说明
- 我把目标数字提前用
const保存了,防止动画过程中因为$(this).text()不断变化导致动画异常; - 把
isResizeble_2 = true移到了complete回调里,确保动画完全跑完后才锁定,避免中途因为滚动再次触发; - 加了节流函数,滚动时每100ms才触发一次可见性检测,减少不必要的函数执行,让页面更流畅;
- 把不需要修改的变量换成了
const,代码更规范。
内容的提问来源于stack exchange,提问作者inrate
相关产品推荐
相关产品推荐

