라이브러리를 사용하지 않고 자동 재생 무한 슬라이드 애니메이션을 만들어 보자.
스타일링 라이브러리는 tailwind-CSS를 사용하여 진행한다.
오른쪽에서 왼쪽으로 진행되는 무한 슬라이드를 구현할 데이터 배열에 translateX을 적용할 경우, 배열이 모두 이동하게 된다면 빈 여백을 표시하게 된다.
이를 채워주기 위해서는 해당 배열의 복사본을 연결시켜 무한 슬라이드를 구현하게 된다.
구현 하기에 두 가지 방법을 고안할 수있다.
아래의 이미지에서 슬라이드 데이터는 임의로 6개로 지정한다.
원본과 복사본으로 두 개의 배열을 만들고, 각각의 애니메이션을 적용한다.
translateX(-100%)
로 이동한다.translateX(0%)
에서 translateX(-200%)
로 이동한다.tailwind-CSS를 적용하면 아래와 같다.
module.exports = {
theme: {
extend: {
keyframes: {
infiniteSlideOriginal: {
"0%": { transform: "translateX(0)" },
"50%": { transform: "translateX(-100%)" },
"50.1%": { transform: "translateX(100%)" },
"100%": { transform: "translateX(0)" },
},
infiniteSlideCopy: {
"0%": { transform: "translateX(0)" },
"100%": { transform: "translateX(-200%)" },
},
},
animation: {
infiniteSlideOriginal: "infiniteSlideOriginal 20s linear infinite",
infiniteSlideCopy: "infiniteSlideCopy 20s linear infinite",
},
},
},
};
원본 배열과 복사본 배열을 하나로 합쳐 하나의 애니메이션을 적용한다.
이 방식은 단일 애니메이션으로 전체 슬라이드가 이동하며, translateX(-50%)
로 이동한다.
module.exports = {
theme: {
extend: {
keyframes: {
infiniteSlide: {
"0%": { transform: "translateX(0)" },
"100%": { transform: "translateX(-50%)" },
},
},
animation: {
infiniteSlide: "infiniteSlide 20s linear infinite",
},
},
},
};
이미 이미지에서는 일부러 데이터 간의 여백을 표시해두었다.
만약, 데이터 배열내에서 gap
을 지정해주었다면 원본+복사본 또는 합쳐진 배열이 한 바퀴가 돌고난 뒤 연결되는 경우에 동일한 여백을 추가해주어야한다.
그렇지 않을 경우, 아래와 같이 데이터 간에 여백이 존재하지 않는 상태로 슬라이드가 연결된다.
각각의 데이터에 스타일링을 적용하거나 배열에서 padding-right
를 적용하는 방법이 있다.
아래 코드는 gap
과 padding-right
를 적용한 하나의 배열, 하나의 애니메이션을 적용한 무한 슬라이드 컴포넌트이다.
export default async function PhotoSlide() {
const { data } = await fetchPixelsPhotos();
const photos = data.photos;
return (
<main className="w-screen h-screen flex justify-center items-center">
<div className="flex w-fit overflow-hidden">
<div className="flex pr-6 gap-6 animate-infiniteSlide">
{[...photos, ...photos].map((photo) => (
<Card
key={photo.id}
description={<p>photo.photographer</p>}
imageSrc={photo.src.large2x}
title={photo.photographer}
/>
))}
</div>
</div>
</main>
);
}
무한히 흘러가는 슬라이드에 사용자가 상호작용을 하거나 데이터를 확인하기 위하여 마우스 hover할 경우에는 멈추는 효과를 추가한다.
tailwind-CSS를 사용하여 스타일링을 적용하며, 이는 다른 스타일링을 사용하거나 순수 CSS을 사용하여도 다른방식을 사용해 동일하게 적용할 수 있다.
// 두 개의 배열, 두 개의 애니메이션
export default async function PhotoSlide() {
const { data } = await fetchPixelsPhotos();
return (
<main className="w-screen h-screen flex justify-center items-center">
<div className="flex w-fit overflow-hidden group">
<div className="flex pr-6 gap-6 animate-infiniteSlide group-hover">
{data.photos.map((photo) => (
<Card
key={photo.id}
description={<p>photo.photographer</p>}
imageSrc={photo.src.large2x}
title={photo.photographer}
/>
))}
</div>
<div className="flex pr-6 gap-6 animate-afterInfiniteSlide group-hover">
{data.photos.map((photo) => (
<Card
key={photo.id}
description={<p>photo.photographer</p>}
imageSrc={photo.src.large2x}
title={photo.photographer}
/>
))}
</div>
</div>
</main>
);
}
// 하나의 배열, 하나의 애니메이션
export default async function PhotoSlide() {
const { data } = await fetchPixelsPhotos();
const photos = data.photos;
return (
<main className="w-screen h-screen flex justify-center items-center">
<div className="flex w-fit overflow-hidden group">
<div className="flex pr-6 gap-6 animate-infiniteSlide group-hover">
{[...photos, ...photos].map((photo) => (
<Card
key={photo.id}
description={<p>photo.photographer</p>}
imageSrc={photo.src.large2x}
title={photo.photographer}
/>
))}
</div>
</div>
</main>
);
}
tailwind-CSS에서는 애니메이션 상태를 일시 정지 시키는 스타일이 존재하지 않기 대문에 CSS를 직접 추가한다.
.group:hover .animate-infiniteSlide {
animation-play-state: paused;
}
.group:hover .animate-afterInfiniteSlide {
animation-play-state: paused;
}
이미지 상에는 마우스 커서가 그렇게 잘 보이진 않는데, 눈 크게 뜨고보면 마우스를 hover 할 때 슬라이드를 일시 정지 시킨다.
주의점을 굳이 쓴 이유는 단지, 내가 구현시에 맞딱드린 어려웠던 부분이기 때문이다.
당시에 저부분이 해결되지 않았던 이유는 아주 기본적인 CSS의 이유였다. 박스모델의 width
에는 margin
이 포함되지 않기때문에 gap
을 적용한다음 padding-right
를 적용해야하는 것을 잊고 margin-right
를 추가하고 있었기 때문이다.
또한, 무한 슬라이드를 구현하기위해 구글링을 많이 해봤더니 무한 슬라이드 일시정지 들을 다양하게 구현하는 것을 확인 할 수 있었다.
순수 CSS로 구현하는 방법이 있는 한편, 자바스크립트로 구현하는 방법도 있었다. 하지만, 자바스크립트로 해당 인터렉션을 관리하게되면 리플로우와 리페인팅이 계속적을 발생된다는 문제점이 발생한다.
순수 CSS로 구현할 수 있는 애니메이션 스타일링이었기 때문에 온전히 GPU에 맡기고 CSS로 무한슬라이드를 구현하는 방법을 선택했다.
오와 대박! animation-play-state라는게 있는거는 처음 알았네요.
유익한 글 잘 보고 갑니다~~ 사진 덕분에 이해가 잘 되네용