如何在Div或CSS类进入浏览器视口时执行jQuery函数且仅运行一次
实现元素进入视口时触发单次jQuery函数
嘿,作为jQuery新手能想到这个需求很棒!你想要的是当目标元素(或者整个容器)进入浏览器视口时,触发一次计数动画,而且确保动画只运行一次对吧?我来帮你调整代码实现这个功能,顺便解释其中的关键点。
核心思路
要实现这个需求,我们需要做到三点:
- 准确判断元素是否进入了视口
- 确保函数只触发一次(给元素加个“已执行”的标记)
- 在滚动/窗口 resize 时监听状态变化(但要避免频繁触发)
修改后的完整代码
HTML 部分
<div id="fico_scroll"> <div id="fico-11"><span class="count">495</span></div> <div id="fico-2"><span class="count">722</span></div> <div id="fico-3"><span class="count">608</span></div> <div id="fico-4"><span class="count">805</span></div> <div id="fico-5"><span class="count">533</span></div> <div id="fico-6"><span class="count">685</span></div> <div style="clear:both"></div> </div>
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; }; // 定义触发动画的函数 function animateCounter($element) { $element.prop('Counter', 0).animate({ Counter: $element.text() }, { duration: 4000, easing: 'swing', step: function(now) { $(this).text(Math.ceil(now)); } }); } // 监听滚动和窗口 resize 事件 $(window).on('resize scroll', function() { // 遍历所有.count元素 $('.count').each(function() { var $this = $(this); // 判断:元素在视口内,且还没执行过动画 if ($this.isInViewport() && !$this.hasClass('animated')) { $this.addClass('animated'); // 添加标记,避免重复执行 animateCounter($this); // 触发动画 } }); });
关键细节解释
- 视口判断插件:
isInViewport函数通过对比元素的位置和视口的位置,返回元素是否在可见区域内,你可以根据需求微调判断条件(比如元素进入视口1/2时再触发)。 - 单次执行控制:我们给已经执行过动画的元素添加
animated类,每次判断时先检查这个类是否存在,确保动画只运行一次。 - 事件监听优化:如果页面滚动频繁,
scroll事件会触发很多次,你可以加入防抖函数来优化性能(比如设置200ms的延迟,避免频繁执行判断逻辑),示例如下:
// 防抖函数 function debounce(func, delay) { let timer; return function() { clearTimeout(timer); timer = setTimeout(func, delay); }; } // 使用防抖包装监听逻辑 $(window).on('resize scroll', debounce(function() { $('.count').each(function() { var $this = $(this); if ($this.isInViewport() && !$this.hasClass('animated')) { $this.addClass('animated'); animateCounter($this); } }); }, 200));
扩展:针对整个容器触发
如果你想当整个 #fico_scroll 容器进入视口时,一次性触发所有计数器动画,只需要调整监听逻辑:
$(window).on('resize scroll', debounce(function() { var $container = $('#fico_scroll'); if ($container.isInViewport() && !$container.hasClass('animated')) { $container.addClass('animated'); $('.count', $container).each(function() { animateCounter($(this)); }); } }, 200));
这样就能确保整个容器进入视口后,所有计数动画只执行一次啦!
内容的提问来源于stack exchange,提问作者Skillz-limited
相关产品推荐
相关产品推荐

