Untitled
unknown
jsx
a year ago
1.3 kB
10
Indexable
import { useEffect, useRef, useState } from "react";
import styled from "styled-components";
const ScUiButton = styled.span`
display: inline-block;
vertical-align: bottom;
&:after {
display: block;
height: 0;
padding-right: 0.5ch;
overflow: hidden;
font-style: normal;
visibility: hidden;
opacity: 0;
content: attr(data-title);
pointer-events: none;
}
`;
const easeOutQuad = (x) => 1 - (1 - x) * (1 - x);
export default function CountUp({ children, duration = 2000 }) {
const [count, setCount] = useState(0);
const countTo = parseInt(children, 10);
const frame = useRef(0);
useEffect(() => {
setTimeout(() => {
const startTime = performance.now();
const tick = (currentTime) => {
const timeElapsed = currentTime - startTime;
const progress = Math.min(timeElapsed / duration, 1);
const easedProgress = easeOutQuad(progress);
setCount(countTo * easedProgress);
if (progress < 1) {
frame.current = requestAnimationFrame(tick);
}
};
frame.current = requestAnimationFrame(tick);
}, 500);
return () => cancelAnimationFrame(frame.current);
}, [countTo, duration]);
return <ScUiButton data-title={children}>{Math.floor(count)}</ScUiButton>;
}
Editor is loading...
Leave a Comment