React组件CSS动画同步:slide-out-tl结束后启动rotate-clockwise
实现React组件中CSS动画的顺序执行:先完成位移动画再无限旋转
我需要在React组件中实现动画同步逻辑:组件渲染时立即播放slide-out-tl位移动画并保留最终帧位置,待该动画结束后,再无限播放rotate-clockwise旋转动画。我尝试通过条件为cover图片添加rotate-clockwise类来实现,相关代码如下:
初始代码
Landing.js
import React from "react"; import logo from "/Sm.png"; import cover from "/logo_cover.png"; import "./Landing.css"; export default function Landing({ rotation, setLoading, setRotation }) { const handleAnimationEnd = () => { setRotation(true); // 启动cover的旋转动画 setLoading((prev) => !prev); // 修正语法 }; return ( <div className="relative z-50"> <img src={cover} alt="cover" className={`cover w-28 absolute top-64 z-10 left-[43rem] animated-slide-out-tl-cover`} onAnimationEnd={handleAnimationEnd} /> <img src={logo} alt="logo" className="logo absolute z-20 top-[13.5rem] left-[41.5rem] scale-110 opacity-100" /> </div> ); }
Landing.css
.animated-slide-out-tl-cover { animation: slide-out-tl 1s ease-in-out 1s forwards; /* 用forwards保留最终关键帧状态 */ } @keyframes slide-out-tl { 0% { transform: translate(0, 0); opacity: 0; } 100% { transform: translate(-555.8px, -231px); opacity: 1; } } @keyframes rotate-clockwise { 0% { transform: translate(-555.8px, -231px); transform: rotate(0deg); /* 从0度开始旋转 */ } 100% { transform: translate(-555.8px, -231px); transform: rotate(360deg); /* 旋转360度完成一个周期 */ } } /* 调整logo的缩放和平移 */ .logo { position: absolute; opacity: 1; animation: logo-animation 1s ease-in-out 1s both; /* 添加1秒延迟 */ transform: scale(1) translate(0, 0); /* 设置初始缩放和平移 */ } @keyframes logo-animation { 0% { transform: translate(0, 0) scale(1); opacity: 1; } 100% { transform: translate(-555.5px, -232px) scale(0.16); opacity: 1; } } .rotate-clockwise { position: absolute; animation: rotate-clockwise 8s infinite 1s linear; /* 为rotate-clockwise添加slide-out-tl动画 */ }
尝试的修改方案
我尝试通过条件渲染为cover图片添加rotate-clockwise类,修改后的代码如下:
import React, { useState } from "react"; import logo from "/Sm.png"; import cover from "/logo_cover.png"; import "./Landing.css"; export default function Landing({ setLoading, setRotation }) { const [animationFinished, setAnimationFinished] = useState(false); const [rotateAnimationStarted, setRotateAnimationStarted] = useState(false); const handleSlideOutEnd = () => { setRotation(true); setAnimationFinished(true); setLoading((prev) => !prev); setRotateAnimationStarted(true); console.log('completed'); }; return ( <div className="relative z-50"> <img src={cover} alt="cover" className={`cover w-28 absolute top-64 z-10 left-[43rem] animated-slide-out-tl-cover ${ animationFinished ? "rotate-clockwise" : "" }`} onAnimationEnd={handleSlideOutEnd} /> <img src={logo} alt="logo" className={`logo absolute z-20 top-[13.5rem] left-[41.5rem] scale-110 opacity-100 ${ rotateAnimationStarted ? "rotate-clockwise" : "" }`} /> </div> ); }
问题分析与解决方案
核心问题
- 旋转动画的transform覆盖问题:
rotate-clockwise动画中写了两个transform属性,后一个会覆盖前一个,导致位移效果丢失,元素会回到初始位置再旋转。 - 动画延迟冗余:
rotate-clockwise类的动画设置了1秒延迟,但此时位移动画已经结束,不需要额外延迟。 - 状态冗余:使用了两个状态控制动画,其实只需要一个状态即可。
修复后的代码
Landing.js
import React, { useState } from "react"; import logo from "/Sm.png"; import cover from "/logo_cover.png"; import "./Landing.css"; export default function Landing({ setLoading }) { const [isSlideOutDone, setIsSlideOutDone] = useState(false); const handleSlideOutEnd = () => { setIsSlideOutDone(true); setLoading(prev => !prev); console.log('位移动画完成,开始旋转'); }; return ( <div className="relative z-50"> <img src={cover} alt="cover" className={`cover w-28 absolute top-64 z-10 left-[43rem] animated-slide-out-tl-cover ${ isSlideOutDone ? "rotate-clockwise" : "" }`} onAnimationEnd={handleSlideOutEnd} /> <img src={logo} alt="logo" className="logo absolute z-20 top-[13.5rem] left-[41.5rem] scale-110 opacity-100" /> </div> ); }
Landing.css
.animated-slide-out-tl-cover { animation: slide-out-tl 1s ease-in-out 1s forwards; } @keyframes slide-out-tl { 0% { transform: translate(0, 0); opacity: 0; } 100% { transform: translate(-555.8px, -231px); opacity: 1; } } /* 合并transform属性,保留位移同时实现旋转 */ @keyframes rotate-clockwise { 0% { transform: translate(-555.8px, -231px) rotate(0deg); } 100% { transform: translate(-555.8px, -231px) rotate(360deg); } } .logo { position: absolute; opacity: 1; animation: logo-animation 1s ease-in-out 1s both; transform: scale(1) translate(0, 0); } @keyframes logo-animation { 0% { transform: translate(0, 0) scale(1); opacity: 1; } 100% { transform: translate(-555.5px, -232px) scale(0.16); opacity: 1; } } /* 移除不必要的延迟,确保位移结束后立即旋转 */ .rotate-clockwise { animation: rotate-clockwise 8s infinite linear; }
关键修改点
- 将
rotate-clockwise动画中的两个transform合并为一个,同时保留位移和旋转属性,避免覆盖。 - 移除
rotate-clockwise类动画的1秒延迟,因为位移动画已经结束,不需要额外等待。 - 简化状态管理,只用
isSlideOutDone一个状态控制旋转类的添加。 - 移除了不必要的
setRotation(若父组件需要该状态可保留)。
内容的提问来源于stack exchange,提问作者Dhruv Kaushik
相关产品推荐
相关产品推荐

