#进度条组件
代码可拓展
✅ 暂停 / 恢复
✅ 变速
✅ 倒退
✅ 精确进度控制
✅ 外部控制开始 / 停止
✅ 同步多个进度条
jsximport { useEffect, useRef, useState } from 'react' import './styles.css' const DURATION = 2000 // 2000ms function ProgressBar() { const [progress, setProgress] = useState(0) const startTimeRef = useRef(null) useEffect(() => { let rafId const animate = timestamp => { if (!startTimeRef.current) { startTimeRef.current = timestamp } const elapsed = timestamp - startTimeRef.current const percentage = Math.min((elapsed / DURATION) * 100, 100) setProgress(percentage) if (percentage < 100) { rafId = requestAnimationFrame(animate) } } rafId = requestAnimationFrame(animate) return () => cancelAnimationFrame(rafId) }, []) return ( <div className="progressbar"> <div className="progress" style={{ width: `${progress}%` }} /> </div> ) } export default function App() { const [count, setCount] = useState(0) const btnClick = () => { setCount(pre => pre + 1) } return ( <div> <button onClick={() => btnClick()}>Add</button> {Array.from({ length: count }, (_, index) => { return <ProgressBar key={index} /> })} </div> ) }
css.progressbar { margin: 10px 0; height: 20px; display: flex; } .progress { background-color: green; }
#react 中使用 requestAnimationFrame 的标准写法
需要在
useEffect 中及时清理jsxuseEffect(() => { let rafId const animate = () => { rafId = requestAnimationFrame(animate) } rafId = requestAnimationFrame(animate) return () => { cancelAnimationFrame(rafId) // ✅ 必须清理 } }, [])
