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

如何让jQuery数字计数脚本仅在元素进入视口时执行?

解决数字滚动组件仅在进入视口时启动的问题

我完全懂你的烦恼——页面一加载数字就滚完了,用户滚动到组件位置时根本看不到动画效果!下面给你两种实用方案,都能让计数动画只在组件进入用户视口时才触发,还能保证只执行一次,不会重复滚动。

方案一:使用Intersection Observer API(推荐,性能更优)

这是现代浏览器原生支持的API,能高效监听元素是否进入视口,不用频繁监听scroll事件,性能友好很多。

修改JavaScript代码

把原有的启动计数的代码替换成以下逻辑(原有的countTo插件代码保留不变):

jQuery(function ($) {
    // 自定义数字格式化逻辑(和原代码一致)
    $('.count-number').data('countToOptions', {
        formatter: function (value, options) {
            return value.toFixed(options.decimals).replace(/\B(?=(?:\d{3})+(?!\d))/g, ',');
        }
    });

    // 计数函数(和原代码一致)
    function count(options) {
        var $this = $(this);
        options = $.extend({}, options || {}, $this.data('countToOptions') || {});
        $this.countTo(options);
    }

    // 创建视口观察实例
    const observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
            // 元素进入视口,且未执行过计数时触发
            if (entry.isIntersecting && !entry.target.classList.contains('count-started')) {
                $(entry.target).addClass('count-started').each(count);
                // 执行后停止监听该元素,节省资源
                observer.unobserve(entry.target);
            }
        });
    }, {
        threshold: 0.1 // 元素10%进入视口时触发,可按需调整
    });

    // 给所有计数元素添加监听
    $('.timer').each(function() {
        observer.observe(this);
    });
});

关键说明

  • threshold: 0.1:表示元素有10%的部分进入视口就启动动画,你可以改成0(刚碰到视口就触发)或1(完全进入视口才触发)。
  • count-started类:用来标记元素已经执行过计数,避免滚动时重复触发动画。

方案二:使用scroll事件监听(兼容旧浏览器)

如果需要兼容不支持Intersection Observer的旧浏览器,可以用这种方法:

步骤1:添加视口检测工具函数

在你的jQuery代码开头先加一个判断元素是否在视口的函数:

$.fn.isInViewport = function() {
    var elementTop = $(this).offset().top;
    var elementBottom = elementTop + $(this).outerHeight();
    var viewportTop = $(window).scrollTop();
    var viewportBottom = viewportTop + $(window).height();
    // 判断元素是否至少有一部分在视口中
    return elementBottom > viewportTop && elementTop < viewportBottom;
};

步骤2:修改启动计数逻辑

把原有的启动代码替换成以下内容:

jQuery(function ($) {
    // 自定义数字格式化逻辑(和原代码一致)
    $('.count-number').data('countToOptions', {
        formatter: function (value, options) {
            return value.toFixed(options.decimals).replace(/\B(?=(?:\d{3})+(?!\d))/g, ',');
        }
    });

    // 计数函数(和原代码一致)
    function count(options) {
        var $this = $(this);
        options = $.extend({}, options || {}, $this.data('countToOptions') || {});
        $this.countTo(options);
    }

    // 监听滚动和页面加载事件
    $(window).on('scroll load', function() {
        $('.timer:not(.count-started)').each(function() {
            if ($(this).isInViewport()) {
                $(this).addClass('count-started').each(count);
            }
        });
    });

    // 页面加载时先检查一次,避免元素一开始就在视口中
    $(window).trigger('scroll');
});

关键说明

  • 同时监听scroll和load事件,确保页面加载时如果元素已经在视口中也能触发动画。
  • 同样用count-started类防止重复触发,避免滚动时动画反复执行。
  • 这种方法会频繁触发scroll事件,性能略逊于方案一,优先推荐用方案一。

测试小提示

  • 测试时可以把浏览器窗口调小,让组件一开始不在视口中,滚动到组件位置看动画是否正常触发。
  • 如果动画没触发,可以调整视口检测的阈值(方案一的threshold,方案二的判断条件)。

内容的提问来源于stack exchange,提问作者xXnikosXx

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:13:03