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

如何优化setTimeout实现的数字计数器,提升动画运行速度?

优化数字计数器动画速度的方案

你的问题核心在于每次仅递增1,且依赖setTimeout的1ms延迟——浏览器对定时器存在最小延迟限制(通常为4ms左右),当目标值达到数千时,需要执行数千次定时器回调,自然会慢得滑稽。以下是两种高效的优化方案:

方案一:固定总时长+requestAnimationFrame(推荐)

不管目标值是100还是10000,都在固定时间内完成动画(比如1.5秒),利用requestAnimationFrame和时间比例计算当前数值,既流畅又高效:

const stat = document.querySelectorAll(".stats span");

export const startCounter = () => {
  stat.forEach(stat => {
    const target = parseInt(stat.dataset.count);
    const duration = 1500; // 动画总时长,单位ms
    let startTime = null;

    function updateCount(timestamp) {
      if (!startTime) startTime = timestamp;
      // 计算已过去时间占总时长的比例,最大不超过1
      const progress = Math.min((timestamp - startTime) / duration, 1);
      // 根据比例计算当前显示数值,取整
      const current = Math.floor(progress * target);
      
      stat.innerText = current.toLocaleString();

      if (progress < 1) {
        requestAnimationFrame(updateCount);
      } else {
        // 最后确保显示准确的目标值
        stat.innerText = target.toLocaleString();
      }
    }

    requestAnimationFrame(updateCount);
  });
};

startCounter();

方案二:动态递增步长

如果不想固定时长,可以根据目标值大小调整每次递增的步长,目标值越大步长越大,避免逐次加1的低效操作:

const stat = document.querySelectorAll(".stats span");

export const startCounter = () => {
  stat.forEach(stat => {
    const target = parseInt(stat.dataset.count);
    let counter = 0;
    // 根据目标值计算步长,取目标值的1%,最少为1
    const step = Math.max(Math.floor(target / 100), 1);

    function updateCount() {
      // 最后一步直接跳到目标值,避免停在接近值
      const next = Math.min(counter + step, target);
      stat.innerText = next.toLocaleString();
      
      if (next < target) {
        requestAnimationFrame(updateCount);
      }
    }

    updateCount();
  });
};

startCounter();

关键优化点说明

  • requestAnimationFrame:比setTimeout更适合动画场景,它会和浏览器刷新频率同步(通常60帧/秒),不会出现定时器堆积或卡顿问题。
  • 避免逐次加1:通过比例或步长计算当前值,大幅减少DOM更新次数,直接提升动画速度。
  • 统一体验:固定时长方案不管数值大小,动画耗时一致,不会出现小数值快、大数值慢的违和感。

内容的提问来源于stack exchange,提问作者Marya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 17:41:11