React循环进度条实现求助:进度完成后自动重复执行
实现自动循环往复的进度条
我需要一个进度条在完成后自动循环往复,目前只能实现进度条满后重置,但必须手动点击按钮才能重启,无法自动循环。
解决方案:结合React状态与动画结束事件实现自动循环
以下是修改后的代码,核心思路是监听动画结束事件,在进度条完成后自动重启动画,同时保留动态设置时长的功能:
React组件代码
import { useState, useRef, useEffect } from 'react'; export default function Home() { const [animationDuration, setAnimationDuration] = useState("0s"); const [isAnimating, setIsAnimating] = useState(false); const [currentDuration, setCurrentDuration] = useState<number>(0); const progressRef = useRef<HTMLDivElement>(null); const handleTimer = (duration: number) => { if (isAnimating) { stopTimer(); } else { startTimer(duration); } }; const startTimer = (duration: number) => { setCurrentDuration(duration); setIsAnimating(true); setAnimationDuration(`${duration / 1000}s`); // 强制重绘以重新触发动画 if (progressRef.current) { progressRef.current.classList.remove("animate-growWidth"); void progressRef.current.offsetWidth; progressRef.current.classList.add("animate-growWidth"); } }; const stopTimer = () => { setIsAnimating(false); setAnimationDuration("0s"); progressRef.current?.classList.remove("animate-growWidth"); }; // 监听动画结束事件,自动重启循环 useEffect(() => { const handleAnimationEnd = () => { if (isAnimating && currentDuration > 0) { startTimer(currentDuration); } }; const element = progressRef.current; element?.addEventListener("animationend", handleAnimationEnd); return () => { element?.removeEventListener("animationend", handleAnimationEnd); }; }, [isAnimating, currentDuration]); return ( <div> <div> <div>Timer</div> <div style={{ position: "relative", width: "300px", height: "16px", border: "1px solid #ddd", borderRadius: "8px" }}> <div ref={progressRef} className={`absolute h-full bg-slate-300 rounded ${isAnimating ? "animate-growWidth" : ""}`} style={{ animationDuration }} ></div> </div> <div style={{ marginTop: "10px" }}> <button onClick={() => handleTimer(1500)} style={{ marginRight: "10px" }}>1.5s</button> <button onClick={() => handleTimer(5000)}>5s</button> </div> </div> </div> ); }
CSS代码
@keyframes growWidth { 0% { width: 0; } 100% { width: 100%; /* 使用百分比适配父容器更灵活 */ } } .animate-growWidth { animation: growWidth linear forwards; }
关键修改说明
- 使用
useRef获取进度条DOM元素,用于监听动画事件和强制重绘触发动画重启。 - 在
animationend事件回调中,若当前处于动画状态,自动调用startTimer重启动画,实现循环效果。 - 重启动画时通过移除/添加动画类+触发重绘的方式,解决CSS动画无法重复触发的问题。
内容的提问来源于stack exchange,提问作者Jebbis
相关产品推荐
相关产品推荐

