My aim is to animate a series of images on my landing page using Next.js and SCSS. The issue arises when I try to add dynamic animations that reset after each cycle. The delay in the animation causes the reset to also be delayed, which disrupts the flow. Is there a way to include the delay within the running animation cycle, so that when it reaches the end, all elements reset simultaneously before adhering to the delay again? Below is the code snippet I am working with:
Carousel.js:
import Image from 'next/image';
import styles from '@/styles/components/LandingCarousel.module.scss';
export default function LandingCarousel() {
const images = [
{ src: '/NetworkingSkeleton.png', delay: 6 },
{ src: '/NetworkingSkeleton.png', delay: 7 },
{ src: '/NetworkingPreview.png', delay: 8 },
{ src: '/NetworkingSkeleton.png', delay: 9 },
{ src: '/NetworkingSkeleton.png', delay: 10 },
{ src: '/NetworkingSkeleton.png', delay: 11 },
{ src: '/NetworkingSkeleton.png', delay: 12 },
{ src: '/NetworkingPreview.png', delay: 13 },
{ src: '/NetworkingSkeleton.png', delay: 14 },
{ src: '/NetworkingSkeleton.png', delay: 15 },
];
const listingImages = [
{ src: '/ListingSkeleton.png', delay: 6 },
{ src: '/ListingSkeleton.png', delay: 7 },
{ src: '/ListingPreview.png', delay: 8 },
{ src: '/ListingSkeleton.png', delay: 9 },
{ src: '/ListingSkeleton.png', delay: 10 },
{ src: '/ListingSkeleton.png', delay: 11 },
{ src: '/ListingPreview.png', delay: 12 },
{ src: '/ListingSkeleton.png', delay: 13 },
];
return (
<div className={styles.section}>
<div className={styles.container}>
{images.map((image, index) => (
<img
key={index}
src={image.src}
className={styles.animated_image}
style={{ '--delay': image.delay }}
/>
))}
</div>
<div className={styles.containerRight}>
{listingImages.map((image, index) => (
<img
key={index}
src={image.src}
className={styles.animated_imageRight}
style={{ '--delay': image.delay }}
/>
))}
</div>
</div>
);
}
LandingCarousel.module.scss:
.section {
display: flex;
height: 87vh;
overflow: hidden;
align-items: center;
.container {
display: flex;
flex-direction: column;
height: calc(400px * 5);
.animated_image {
display: flex;
position: relative;
max-height: 400px;
object-fit: cover;
animation: scroll 8s ease-in-out infinite;
-webkit-animation: scroll 8s ease-in-out infinite;
// animation-delay: calc(var(--delay) * 0.05s);
// -webkit-animation-delay: calc(var(--delay) * 0.05s);
}
}
.containerRight {
display: flex;
flex-direction: column;
height: calc(380px * 4);
.animated_imageRight {
display: flex;
max-height: 380px;
object-fit: cover;
animation: scrollRight 8s ease-in-out infinite;
-webkit-animation: scrollRight 8s ease-in-out infinite;
// animation-delay: calc(var(--delay) * 0.05s);
// -webkit-animation-delay: calc(var(--delay) * 0.05s);
}
}
}
@keyframes scroll {
0% {
-webkit-transform: translateY(0);
transform: translateY(0);
}
50% {
-webkit-transform: translateY(-400px * 5);
transform: translateY(-400px * 5);
}
100% {
-webkit-transform: translateY(-400px * 5);
transform: translateY(-400px * 5);
}
}
@keyframes scrollRight {
0% {
-webkit-transform: translateY(0);
transform: translateY(0);
}
50% {
-webkit-transform: translateY(-380px * 4);
transform: translateY(-380px * 4);
}
100% {
-webkit-transform: translateY(-380px * 4);
transform: translateY(-380px * 4);
}
}