forked from codechefPesuecc/CodeChef-PESUECC-Chapter
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCountUp.tsx
More file actions
50 lines (42 loc) · 1.2 KB
/
Copy pathCountUp.tsx
File metadata and controls
50 lines (42 loc) · 1.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
"use client";
import { useEffect, useRef, useState } from "react";
import { useInView } from "motion/react";
type CountUpProps = {
value: number;
prefix?: string;
suffix?: string;
durationMs?: number;
className?: string;
};
export default function CountUp({
value,
prefix = "",
suffix = "",
durationMs = 1600,
className,
}: CountUpProps) {
const ref = useRef<HTMLSpanElement>(null);
const inView = useInView(ref, { once: true, margin: "-80px" });
const [display, setDisplay] = useState(0);
useEffect(() => {
if (!inView) return;
let raf = 0;
let startTime = 0;
const tick = (now: number) => {
if (!startTime) startTime = now;
const progress = Math.min((now - startTime) / durationMs, 1);
const eased = 1 - Math.pow(1 - progress, 3); // easeOutCubic
setDisplay(Math.round(eased * value));
if (progress < 1) raf = requestAnimationFrame(tick);
};
raf = requestAnimationFrame(tick);
return () => cancelAnimationFrame(raf);
}, [inView, value, durationMs]);
return (
<span ref={ref} className={`${className || ""} tabular-nums`} suppressHydrationWarning>
{prefix}
{display.toLocaleString()}
{suffix}
</span>
);
}