jQuery Counter Up组件重复滚动触发计数异常问题求助
解决Counter Up组件重复滚动触发异常的问题
问题原因
原始代码中,Counter Up插件首次执行后会将目标元素的内容替换为最终计数结果,同时默认只会执行一次。当再次滚动到该区域时,插件要么尝试从当前已完成的数值重新计数(无动画效果),要么因元素被标记为已执行而中途停止,导致计数器停在随机数字。
解决方案
通过保存原始目标值、重置元素状态并监听滚动触发的方式,确保每次元素进入可视区域时都能完整执行计数动画:
修改后的HTML代码
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="row g-4 mb-4"> <div class="col-sm-6"> <div class="d-flex align-items-center border-start border-5 border-primary px-3"> <!-- 用data-target存储原始目标值,初始文本设为0 --> <h1 class="about-numbers counter" data-target="10">0</h1> <div class="ps-4"> <p class="mb-0 about-text">Years of</p> <h6 class="text-uppercase mb-0 about-bold">Experience</h6> </div> </div> </div> <div class="col-sm-6"> <div class="d-flex align-items-center border-start border-5 border-primary px-3"> <h1 class="about-numbers">+</h1> <!-- 同样设置data-target和初始值 --> <h1 class="about-numbers counter" data-target="5000">0</h1> <div class="ps-4"> <p class="mb-0 about-text">Products</p> <h6 class="text-uppercase mb-0 about-bold">Sold</h6> </div> </div> </div> </div>
改进后的JavaScript代码
$(document).ready(function() { // 判断元素是否进入可视区域 function isInViewport(element) { const rect = element.getBoundingClientRect(); return rect.top <= window.innerHeight && rect.bottom >= 0; } // 处理计数器逻辑 function handleCounters() { $('.counter').each(function() { const $counter = $(this); const targetValue = $counter.data('target'); if (isInViewport(this) && !$counter.hasClass('triggered')) { // 重置计数器状态:移除插件标记,恢复初始值 $counter.removeClass('counterUp').text('0'); // 重新调用Counter Up执行计数动画 $counter.counterUp({ delay: 10, time: 500 }); // 添加触发标记,避免短时间内重复执行 $counter.addClass('triggered'); } else if (!isInViewport(this)) { // 离开可视区域后移除标记,允许下次进入时重新触发 $counter.removeClass('triggered'); } }); } // 防抖函数:减少滚动时的函数调用频率,优化性能 function debounce(func, wait) { let timeout; return function(...args) { clearTimeout(timeout); timeout = setTimeout(() => func.apply(this, args), wait); }; } // 首次加载检查一次 handleCounters(); // 绑定防抖后的滚动监听事件 $(window).scroll(debounce(handleCounters, 100)); });
核心优化点
- 存储原始目标值:通过
data-target属性保存计数器的最终目标值,避免依赖被插件修改后的元素文本。 - 重置元素状态:每次触发计数前,将元素文本恢复为初始值(0),并移除插件添加的
counterUp类,确保插件可以重新执行动画。 - 可视区域判断:仅当元素进入可视区域时触发计数,离开时清除触发标记,保证下次进入时能重新执行。
- 防抖优化:减少滚动事件的函数调用次数,避免页面性能损耗。
内容的提问来源于stack exchange,提问作者Camilo Agudelo
相关产品推荐
相关产品推荐

