You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:10:12