39 lines
981 B
TypeScript
39 lines
981 B
TypeScript
"use client";
|
|
|
|
import { useEffect, useRef, useState } from "react";
|
|
import { useInView } from "framer-motion";
|
|
|
|
export function CountUp({
|
|
end,
|
|
suffix = "",
|
|
duration = 1800,
|
|
}: {
|
|
end: number;
|
|
suffix?: string;
|
|
duration?: number;
|
|
}) {
|
|
const ref = useRef<HTMLSpanElement>(null);
|
|
const inView = useInView(ref, { once: true, margin: "-60px" });
|
|
const [val, setVal] = useState(0);
|
|
|
|
useEffect(() => {
|
|
if (!inView) return;
|
|
let raf = 0;
|
|
const t0 = performance.now();
|
|
const tick = (t: number) => {
|
|
const p = Math.min(1, (t - t0) / duration);
|
|
setVal(Math.round(end * (1 - Math.pow(1 - p, 3))));
|
|
if (p < 1) raf = requestAnimationFrame(tick);
|
|
};
|
|
raf = requestAnimationFrame(tick);
|
|
return () => cancelAnimationFrame(raf);
|
|
}, [inView, end, duration]);
|
|
|
|
return (
|
|
<span ref={ref} className="tabular-nums">
|
|
{val.toLocaleString("fa-IR")}
|
|
{suffix && <span className="text-accent">{suffix}</span>}
|
|
</span>
|
|
);
|
|
}
|