<div class="number" data-target="100">0</div>
<div class="number" data-target="200">0</div>
<div class="number" data-target="300">0</div>

      body,
      html {
        height: 300%;
      }
      .number {
        position: relative;
        top: 200px;
        font-size: 30px;
        font-weight: bold;
        text-align: center;
        margin-top: 400px;
      }
document.addEventListener("DOMContentLoaded", function () {
  const observer = new IntersectionObserver(
    (entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          const target = entry.target;
          const finalNumber = parseInt(target.dataset.target, 10);
          const duration = 1000; // アニメーションの継続時間 (ミリ秒)
          let start = null;

          function step(timestamp) {
            if (!start) start = timestamp;
            const progress = timestamp - start;
            const currentNumber = Math.min(
              finalNumber,
              Math.floor((progress / duration) * finalNumber)
            );
            target.textContent = currentNumber;
            if (currentNumber < finalNumber) {
              window.requestAnimationFrame(step);
            } else {
              observer.unobserve(target); // アニメーション完了後に監視を停止
            }
          }

          window.requestAnimationFrame(step);
        }
      });
    },
    {
      threshold: 0.5, // 要素が50%表示された時にトリガー
    }
  );

  const numbers = document.querySelectorAll(".number");
  numbers.forEach((number) => observer.observe(number));
});
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.