You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

滚动触发数字计数器回落问题求助:期望仅递增后停止

Hey,我帮你找到了问题所在!你的数字计数器滚动到可见区域后跑到85又回落,核心是一个低级拼写错误在搞鬼,还有几个小细节可以优化,下面给你讲清楚:

解决滚动触发数字计数器重复回落的问题

问题核心原因

你在first_num_count函数里,把变量isResizeble_2拼写成了isRezeble_2!这就导致这个用来阻止重复执行的标识永远不会被设为true,每次滚动触发first_num_count时,都会重新启动数字动画——jQuery的animate是队列执行的,前一次动画刚到85,后一次又从0开始,看起来就像回落了。

另外还有个小问题:滚动事件会频繁触发,虽然你加了isResizeble_1,但用节流函数优化一下会更稳妥。

修复方案

  1. 修正拼写错误:把isRezeble_2 = true改成isResizeble_2 = true,这是最关键的一步;
  2. 优化动画逻辑:提前保存目标数字,避免动画过程中获取到变化的文本值;把标识锁定放在动画完成回调里,确保动画结束后才不再执行;
  3. 滚动事件节流:减少滚动时的函数触发频率,提升页面性能。

修正后的完整代码

<!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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:43:44