-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathanimate-number.tsx
41 lines (37 loc) · 1.12 KB
/
animate-number.tsx
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
'use client';
import { useEffect } from 'react';
import { MotionValue, motion, useSpring, useTransform } from 'framer-motion';
interface AnimatedNumberProps {
value: number;
mass?: number;
stiffness?: number;
damping?: number;
precision?: number;
format?: (value: number) => string;
onAnimationStart?: () => void;
onAnimationComplete?: () => void;
}
export function AnimatedNumber({
value,
mass = 0.8,
stiffness = 75,
damping = 15,
precision = 0,
format = (num) => num.toLocaleString(),
onAnimationStart,
onAnimationComplete,
}: AnimatedNumberProps) {
const spring = useSpring(value, { mass, stiffness, damping });
const display: MotionValue<string> = useTransform(spring, (current) =>
format(parseFloat(current.toFixed(precision)))
);
useEffect(() => {
spring.set(value);
if (onAnimationStart) onAnimationStart();
const unsubscribe = spring.onChange(() => {
if (spring.get() === value && onAnimationComplete) onAnimationComplete();
});
return () => unsubscribe();
}, [spring, value, onAnimationStart, onAnimationComplete]);
return <motion.span>{display}</motion.span>;
}