
이번에 구현해본 애니메이션은 슬라이드 넘기기 애니메이션과 자동 슬라이드 입니다.
제가 구현하고 있는 서비스에 로그인 시 가장 처음 만나는 화면이기 때문에 단순히 나열해 놓은 포스터와 그 정보들을 애니메이션 없이 넘기면서 보는 것은 사용자 입장에서 재미가 없을 것 같다고 생각하였습니다.
4초 마다 자동으로 넘어가기도 하고 직접 좌측, 우측의 화살표를 눌러 넘길 수 있습니다.
그리고 넘어가는 과정이 애니메이션을 통해 부드럽게 넘어갑니다.
사진을 한줄로 배치하고 translateX 값을 통해 해당 사진으로 움직이게 합니다.
그리고 animation duration으로 부드럽게 움직이게 하였습니다.
일단 어플의 너비를 넘어가는 사진을 한줄로 배치합니다.
한줄로 배치하는 방법은 사진을 감싸는 element의 속성에 inline-block을 추가하면 됩니다.
구현 코드
tailwindCSS를 사용하였습니다.
<li className="relative inline-block w-full h-full">
<button className="absolute top-[8.5rem] z-10" />
<div className="absolute" />
<img className="w-full h-full object-fit" src={image} />
<button className="absolute top-[8.5rem] z-10 right-1" />
</li>
생략된 코드들이 있지만 기본 원리는 사진들 중 각각의 항목의 가장 바깥 element에 inline-block 속성을 주시면 한줄로 배치됩니다. 그리고 relative 속성을 주고 사진 관련 정보 및 좌우 화살표에 absolute 속성을 주고 배치해주시면 됩니다.
그리고 이 li를 감싸는 ul에 overflow-hidden 속성을 주면 어플에는 처음 사진만 보이고 다른 사진들은 안보이게 됩니다.

우선 현재 사진의 상태를 지정합니다.
const [currentPosterNum, setCurrentPosterNum] = useState(0);
그리고 ul에 duration 속성과 style 속성으로 translateX 속성을 줍니다.
translateX 속성은 0%일 경우 제자리에 있고, -100%일 경우 왼쪽으로 사진 너비만큼 넘어가게 됩니다. 이런 식으로 계속해서 다음 사진으로 넘어가는 방식입니다.
<ul
className="w-full h-full duration-500"
style={{ transform: `translateX(-${currentPosterNum}00%)` }}
>
// ...후략
state에 의해 동적으로 변하는 css의 경우 tailwindCSS와 어울리지 않습니다. tailwindCSS는 정적 CSS이기 때문에 동적인 값이 주어질 경우 제대로 작동되지 않을 수 있습니다. 그래서 translateX의 값을 style에 주었습니다.
왼쪽 오른쪽 버튼을 눌렀을 때 다음 사진으로 넘어가는 버튼입니다.
<button
onClick={() => {
setCurrentPosterNum((prev) => (prev - 1 + posterLength) % posterLength)}
}
>
// ... 중략
<button
onClick={() => {
setCurrentPosterNum((prev) => (prev + 1 + posterLength) % posterLength)}
}
>
setCurrentPosterNum에 들어가 있는 식을 통해 상태를 변경하는 이유는 첫 번째 사진에서 뒤로 가는 버튼을 눌렀을 때 마지막 사진으로 이동되고, 마지막 사진에서 앞으로 가는 버튼을 눌렀을 때 처음 사진으로 이동하기 위한 식입니다.
마지막으로 useEffect와, setInterval을 통해 자동 슬라이드를 구현하면 됩니다.
useEffect(() => {
const interval = setInterval(() => {
setCurrentPosterNum(
(prev) => (prev + 1 + posters.length) % posters.length,
);
}, 4000);
return () => {
clearInterval(interval);
};
}, [posters]);