Untitled
unknown
jsx
5 months ago
1.3 kB
4
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