如何修改JavaScript数字递增动画的步长
实现数字递增动画的自定义步长需求
问题描述
我正在研究一个JavaScript数字递增动画示例,希望修改计数动作的步长——即按2、3、5等数值递增,而非每次加1。目前尝试修改了frame变量的值,以及调整totalFrames和progress相关数值,但都无法实现不同步长,求实现方法。
原代码如下:
HTML代码
<button onclick="runAnimations()">Animate</button> <ul> <li><span class="countup">45</span></li> <li><span class="countup">110</span></li> <li><span class="countup">53210</span></li> </ul>
JavaScript代码
// How long you want the animation to take, in ms const animationDuration = 10000; // Calculate how long each ‘frame’ should last if we want to update the animation 60 times per second const frameDuration = 1000 / 60; // Use that to calculate how many frames we need to complete the animation const totalFrames = (Math.round( animationDuration / frameDuration ) + 5); // An ease-out function that slows the count as it progresses const easeOutQuad = t => t * ( 2 - t ); // The animation function, which takes an Element const animateCountUp = el => { let frame = 0; const countTo = parseInt( el.innerHTML, 10 ); // Start the animation running 60 times per second const counter = setInterval( () => { frame++; // Calculate our progress as a value between 0 and 1 // Pass that value to our easing function to get our // progress on a curve const progress = easeOutQuad( frame / totalFrames ); // Use the progress value to calculate the current count const currentCount = Math.round( countTo * progress ); // If the current count has changed, update the element if ( parseInt( el.innerHTML, 10 ) !== currentCount ) { el.innerHTML = currentCount; } // If we’ve reached our last frame, stop the animation if ( frame === totalFrames ) { clearInterval( counter ); } }, frameDuration ); }; // Run the animation on all elements with a class of ‘countup’ const runAnimations = () => { const countupEls = document.querySelectorAll( '.countup' ); countupEls.forEach( animateCountUp ); };
解决方案
原代码逻辑是通过进度比例直接计算当前数值,并非按步长累加,所以修改frame等参数无法实现步长控制。我们需要调整逻辑,基于步长计算每帧的显示值,同时保留缓动效果:
- 为每个计数元素添加自定义步长(通过
data-step属性),也可设置全局默认步长 - 计算总整数步数与最后一步的余数,避免最终值偏差
- 利用缓动后的进度值,计算当前完成的步数,再乘以步长得到当前显示值,最后处理收尾余数
修改后的完整代码
HTML(添加data-step自定义步长)
<button onclick="runAnimations()">Animate</button> <ul> <li><span class="countup" data-step="3">45</span></li> <li><span class="countup" data-step="5">110</span></li> <li><span class="countup" data-step="100">53210</span></li> </ul>
JavaScript
const animationDuration = 10000; const frameDuration = 1000 / 60; const totalFrames = Math.round(animationDuration / frameDuration) + 5; const easeOutQuad = t => t * (2 - t); const animateCountUp = el => { let frame = 0; const countTo = parseInt(el.innerHTML, 10); // 获取元素自定义步长,默认步长为1 const step = parseInt(el.dataset.step || 1, 10); // 计算总整数步数和最后一步的余数 const totalFullSteps = Math.floor(countTo / step); const remainder = countTo % step; const counter = setInterval(() => { frame++; const progress = easeOutQuad(frame / totalFrames); // 根据进度计算当前完成的步数 const currentSteps = Math.round(totalFullSteps * progress); // 当前显示值 = 已完成步数 * 步长 let currentCount = currentSteps * step; // 动画最后一帧补全余数,确保最终值准确 if (frame === totalFrames) { currentCount = countTo; } if (parseInt(el.innerHTML, 10) !== currentCount) { el.innerHTML = currentCount; } if (frame === totalFrames) { clearInterval(counter); } }, frameDuration); }; const runAnimations = () => { const countupEls = document.querySelectorAll('.countup'); countupEls.forEach(animateCountUp); };
说明
- 每个
.countup元素可通过data-step属性设置专属步长,未设置的元素默认按步长1递增 - 保留原有的缓动效果,动画后期会自然减速
- 最后一帧强制设置为目标值,避免因取整导致的最终值偏差
内容的提问来源于stack exchange,提问作者Jon
相关产品推荐
相关产品推荐

