直接贴代码食用

Tips:此代码会读取将页面中所有带counter类名的元素,使用时设置 data-start(起始值)data-end(结束值) 两个自定义属性值即可
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
      body {
        height: 100vh;
        display: flex;
        align-items: center;
        justify-content: center;
      }
      .counter {
        font-size: 36px;
        font-weight: bold;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <div class="counter" data-start="0" data-end="189478328">0</div>

    <script>
      /**
       * 数字滚动特效
       * @param {number} duration 动画持续时间
       */
      const counterLoader = (duration) => {
        const easeInOut = (t) => {
          return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
        };

        /**
         * 动画
         * @param {HTMLElement} counterElement 计数器元素
         * @param {number} startTime 开始时间
         * @param {number} startValue 开始值
         * @param {number} endValue   结束值
         */
        const animateCounter = (
          counterElement,
          startTime,
          startValue,
          endValue
        ) => {
          const currentTime = Date.now();
          const elapsedTime = currentTime - startTime;

          const progress = elapsedTime / duration;
          const easedProgress = easeInOut(progress);

          const currentValueAnimated =
            startValue + (endValue - startValue) * easedProgress;

          counterElement.textContent = Math.round(currentValueAnimated);

          if (progress < 1) {
            requestAnimationFrame(() =>
              animateCounter(counterElement, startTime, startValue, endValue)
            );
          }
        };

        // 获取计数器元素
        const counterElements = Array.from(
          document.querySelectorAll(".counter")
        );

        // 遍历执行动画
        counterElements.forEach((element) => {
          const startValue = parseFloat(element.dataset.start);
          const endValue = parseFloat(element.dataset.end);

          animateCounter(element, Date.now(), startValue, endValue);
        });
      };

      counterLoader(2000);
    </script>
  </body>
</html>
文章目录