Animations/Number Ticker

Number Ticker

Compteurs animes qui grimpent de 0 a la valeur cible avec easing. Declenches au scroll.

scrollJScounterstatsdashboard
Trigger: Scroll (IntersectionObserver)
CSS requis: Non
Difficulte: easy

Preview live

Code

"use client";
import { useRef, useState, useEffect } from "react";

function easeOutExpo(t: number) {
  return t === 1 ? 1 : 1 - Math.pow(2, -10 * t);
}

export default function NumberTicker({ target = 1234, duration = 2000 }) {
  const [value, setValue] = useState(0);
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const observer = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) {
        const start = performance.now();
        const animate = (now: number) => {
          const elapsed = now - start;
          const progress = Math.min(elapsed / duration, 1);
          setValue(Math.round(easeOutExpo(progress) * target));
          if (progress < 1) requestAnimationFrame(animate);
        };
        requestAnimationFrame(animate);
        observer.disconnect();
      }
    }, { threshold: 0.5 });
    if (ref.current) observer.observe(ref.current);
    return () => observer.disconnect();
  }, [target, duration]);

  return <div ref={ref}>{value.toLocaleString()}</div>;
}

Instructions

Compteur anime avec easeOutExpo pour un ralentissement progressif. Declenche au scroll (IntersectionObserver, threshold 0.5). Ajustez target et duration en props. toLocaleString() ajoute les separateurs de milliers.