Skip to content

Instantly share code, notes, and snippets.

@RTAndrew
Created March 10, 2025 00:26
Show Gist options
  • Save RTAndrew/de6ec7590a15de388211db33b1747464 to your computer and use it in GitHub Desktop.
Save RTAndrew/de6ec7590a15de388211db33b1747464 to your computer and use it in GitHub Desktop.
React Animated Number
import React, { useState, useEffect, useRef } from 'react';
import { cn } from '@/lib/utils';
interface AnimatedNumberProps {
value: number;
duration?: number;
className?: string;
suffix?: string;
prefix?: string;
decimals?: number;
delay?: number;
threshold?: number;
}
const AnimatedNumber: React.FC<AnimatedNumberProps> = ({
value,
duration = 2000,
className,
suffix = '',
prefix = '',
decimals = 0,
delay = 0,
threshold = 0.1,
}) => {
const [count, setCount] = useState(0);
const countRef = useRef<HTMLSpanElement>(null);
const startedRef = useRef(false);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting && !startedRef.current) {
startedRef.current = true;
setTimeout(() => {
const startTime = Date.now();
const startValue = 0;
const updateCount = () => {
const now = Date.now();
const progress = Math.min((now - startTime) / duration, 1);
const easedProgress = easeOutQuart(progress);
const currentValue = startValue + (value - startValue) * easedProgress;
setCount(currentValue);
if (progress < 1) {
requestAnimationFrame(updateCount);
}
};
requestAnimationFrame(updateCount);
}, delay);
observer.unobserve(entry.target);
}
},
{ threshold }
);
if (countRef.current) {
observer.observe(countRef.current);
}
return () => {
if (countRef.current) {
observer.unobserve(countRef.current);
}
};
}, [value, duration, delay, threshold]);
// Easing function for smoother animation
const easeOutQuart = (x: number): number => {
return 1 - Math.pow(1 - x, 4);
};
return (
<span ref={countRef} className={cn('font-display', className)}>
{prefix}
{count.toFixed(decimals)}
{suffix}
</span>
);
};
export default AnimatedNumber;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment