如何在JavaScript中实现指定时长的数值过渡动画函数?
实现指定时长内数值过渡的JavaScript函数
嘿,我懂这种感觉!本来以为写个数值过渡函数很简单,结果实际动手才发现坑不少,大概率是累了脑子转不动啦😉。给你几种靠谱的实现方式,适配不同的需求:
基础线性过渡(setInterval 版本)
适合简单场景,实现起来直观,精度足够应对大多数普通需求:
let varToChange = 0; // 注意要改成let,const无法重新赋值 const targetValue = 100; const duration = 2; // 秒 function changeValueOverTime(target, timeInSeconds) { const startTime = Date.now(); const startValue = varToChange; const totalMs = timeInSeconds * 1000; const valueDifference = target - startValue; // 约16ms执行一次,匹配60fps屏幕刷新率 const intervalId = setInterval(() => { const elapsedTime = Date.now() - startTime; // 计算进度,确保不超过100% const progress = Math.min(elapsedTime / totalMs, 1); varToChange = startValue + valueDifference * progress; // 完成过渡后清除定时器,强制设置为目标值避免误差 if (progress >= 1) { varToChange = target; clearInterval(intervalId); console.log("过渡完成!当前值:", varToChange); } }, 16); } // 调用函数 changeValueOverTime(targetValue, duration);
流畅过渡(requestAnimationFrame 版本)
如果需要更流畅的动画效果,推荐用浏览器专门为动画设计的requestAnimationFrame,它会和浏览器重绘同步,避免卡顿:
let varToChange = 0; const targetValue = 100; const duration = 2; // 秒 function changeValueOverTime(target, timeInSeconds) { const startTime = performance.now(); const startValue = varToChange; const totalMs = timeInSeconds * 1000; const valueDifference = target - startValue; function updateValue(currentTime) { const elapsedTime = currentTime - startTime; const progress = Math.min(elapsedTime / totalMs, 1); varToChange = startValue + valueDifference * progress; if (progress < 1) { // 继续下一帧更新 requestAnimationFrame(updateValue); } else { varToChange = target; console.log("过渡完成!当前值:", varToChange); } } // 启动动画 requestAnimationFrame(updateValue); } // 调用函数 changeValueOverTime(targetValue, duration);
进阶:添加缓动效果
如果想要更自然的过渡(比如缓入缓出),可以增加一个缓动函数参数,实现非线性过渡:
let varToChange = 0; const targetValue = 100; const duration = 2; // 秒 // 示例缓动函数:缓入缓出(Quad曲线) function easeInOutQuad(t) { return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t; } function changeValueOverTime(target, timeInSeconds, easing = (t) => t) { const startTime = performance.now(); const startValue = varToChange; const totalMs = timeInSeconds * 1000; const valueDifference = target - startValue; function updateValue(currentTime) { const elapsedTime = currentTime - startTime; const linearProgress = Math.min(elapsedTime / totalMs, 1); // 应用缓动效果 const easedProgress = easing(linearProgress); varToChange = startValue + valueDifference * easedProgress; if (linearProgress < 1) { requestAnimationFrame(updateValue); } else { varToChange = target; console.log("过渡完成!当前值:", varToChange); } } requestAnimationFrame(updateValue); } // 调用时使用缓入缓出效果 changeValueOverTime(targetValue, duration, easeInOutQuad);
注意事项
- 一定要把
varToChange声明为let,const无法被重新赋值,这是你代码里的一个小问题~ - 如果需要支持暂停/取消过渡,可以保存
requestAnimationFrame返回的ID或者setInterval的ID,然后调用cancelAnimationFrame或clearInterval终止过程。
内容的提问来源于stack exchange,提问作者Syler
相关产品推荐
相关产品推荐

