Certainly! I am seeking assistance with synchronizing CSS animations within a React component. Specifically, you want to ensure that one animation (`slide-out-tl`) plays immediately upon component rendering, maintaining its final position, while another animation (`rotate-clockwise`) starts infinitely only after the first animation concludes.
// 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); // Start rotating the cover
setLoading((prev) => !prev); // Corrected syntax
};
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>
);
}
.animated-slide-out-tl-cover {
animation: slide-out-tl 1s ease-in-out 1s forwards; /* Change 'both' to 'forwards' to retain final keyframe */
}
@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); /* Start rotating from 0 degrees */
}
100% {
transform: translate(-555.8px, -231px);
transform: rotate(360deg); /* Rotate 360 degrees for a full cycle */
}
}
/* Adjust the scale and translation of the logo */
.logo {
position: absolute;
opacity: 1;
animation: logo-animation 1s ease-in-out 1s both; /* Add 1 second delay */
transform: scale(1) translate(0, 0); /* Set initial scale and translation */
}
@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; /* Add slide-out-tl animation to rotate-clockwise */
}
I tried conditionally adding rotate-clockwise class to cover image like this->
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>
);
}
There is no need to conditionally add rotate-clockwise
class. In fact, both animation needs to be specified together separated by a comma, or the first animation will be overwriten. Since slide-out-tl
have a 1 second duration and 1 second delay, simply set a 2 second delay on rotate-clockwise
.
Next, since both animation is sharing the transform
property, it will still be overwritten even if you are using forward
. To retain translate(-555.8px, -231px)
from the first animation, you need to include it in the second animation's transform in the same line.
.animated-slide-out-tl-cover {
animation:
slide-out-tl 1s ease-in-out 1s forwards,
rotate-clockwise 8s linear 2s infinite;
}
@keyframes slide-out-tl {
0% {
transform: translate(0, 0);
opacity: 0;
}
100% {
transform: translate(-555.8px, -231px);
opacity: 1;
}
}
@keyframes rotate-clockwise {
0% {
/* retain the translated position from the last frame of the previous animation */
transform: translate(-555.8px, -231px) rotate(0deg);
}
100% {
transform: translate(-555.8px, -231px) rotate(360deg);
}
}
/* Adjust the scale and translation of the logo */
.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;
}
}
export default function Landing({ setLoading, setRotation }) {
const handleSlideOutEnd = () => {
setRotation(true);
setLoading((prev) => !prev);
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 `}
onAnimationEnd={handleSlideOutEnd}
/>
<img
src={logo}
alt="logo"
className={`logo absolute z-20 top-[13.5rem] left-[41.5rem] scale-110 opacity-100`}
/>
</div>
);
}