You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>
  );
}

问题分析与解决方案

核心问题

  1. 旋转动画的transform覆盖问题:rotate-clockwise动画中写了两个transform属性,后一个会覆盖前一个,导致位移效果丢失,元素会回到初始位置再旋转。
  2. 动画延迟冗余:rotate-clockwise类的动画设置了1秒延迟,但此时位移动画已经结束,不需要额外延迟。
  3. 状态冗余:使用了两个状态控制动画,其实只需要一个状态即可。

修复后的代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 22:35:00