如何实现每次滚动至指定区块时触发数字递增动画?
解决滚动触发数字递增重复执行问题
问题原因分析
移除!viewed后出现数字反向递减,核心问题有两点:
- 动画执行时会修改元素的
text内容,再次触发时,jQuery(this).text()取到的是动画中的中间值而非原始目标值,若当前动画进度已经超过这个中间值,就会出现反向递减。 - 多次触发动画时未停止之前的动画实例,导致多个动画冲突,数值跳动异常。
修复方案
我们需要先把每个数字的原始目标值存起来(用data-*属性),每次触发动画前停止已有动画,再从0开始递增到原始目标值:
// 初始化:把每个.value的原始文本存到data-target属性里 jQuery('.value').each(function() { jQuery(this).data('target', jQuery(this).text()); }); var isAnimating = false; // 避免滚动时频繁触发 function isScrolledIntoView(elem) { var docViewTop = jQuery(window).scrollTop(); var docViewBottom = docViewTop + jQuery(window).height(); var elemTop = jQuery(elem).offset().top; var elemBottom = elemTop + jQuery(elem).height(); return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); } function testScroll() { var $numbers = jQuery(".numbers"); if (isScrolledIntoView($numbers) && !isAnimating) { isAnimating = true; jQuery('.value').each(function () { // 停止当前元素的所有动画,避免冲突 jQuery(this).stop(true, true); // 从0开始动画到存储的原始目标值 jQuery(this).prop('Counter',0).animate({ Counter: jQuery(this).data('target') }, { duration: 4000, easing: 'swing', step: function (now) { jQuery(this).text(Math.ceil(now)); }, complete: function() { // 动画完成后允许再次触发 isAnimating = false; } }); }); } else if (!isScrolledIntoView($numbers)) { // 当元素滚出视图时,重置数值为0(可选,根据需求调整) jQuery('.value').text(0); isAnimating = false; } } // 绑定滚动事件 jQuery(window).on('scroll', testScroll); // 页面加载时先检查一次位置 jQuery(document).ready(function() { testScroll(); });
关键改动说明
- 用
data-target存储每个数字的原始目标值,避免动画修改text后丢失原始值。 - 添加
isAnimating状态锁,防止滚动时频繁触发动画,导致性能问题和数值异常。 - 每次执行动画前调用
stop(true, true),停止当前元素的所有未完成动画,清空动画队列并直接跳到结束状态,避免冲突。 - 可选:当元素滚出视图时重置数值为0,这样每次滚入都会重新从0开始递增(如果不需要重置,去掉else if部分即可)。
内容的提问来源于stack exchange,提问作者fjimenez
相关产品推荐
相关产品推荐

