React 슬라이딩 캐러셀 만드는 법 (Slider, Carousel)
이전에 진행했던 ‘디스트리’ 프로젝트에서 끊기지 않는 무한 슬라이딩 캐러셀을 만들어보려다 실패한 경험이 있다. 당시에는 react는 물론이고 javascript도 잘 다루지 못했던 때라 이번 기회를 빌어 무한 슬라이딩 캐러셀 제작법을 정리해보려 한다.
메인 컨셉
가장 중요한 구현 컨셉은, 양쪽에 fake 배너를 만들어줘서 눈속임을 줘야 한다는 것이다.
물론 실제로 모든 배너들이 3D로 연결되어 무한 슬라이딩을 구현하면 좋겠지만 쉽지 않은 것이 현실이다.
따라서 아래와 같이 가짜 배너를 양 끝에 배치시켜야 한다. 이해가 아직은 쉽지 않을 수 있는데 두 번째 그림을 보면 쉽게 이해될 수도 있다.
쉽게 설명하면 transition
의 특성을 이용한 것이다.
우리는 각 슬라이드들이 넘어가는 것을 어떻게 인지할까?
첫 째,그림이 바뀌는 것을 인지하는 것, 그리고 둘 째, 같은 그림이더라도 넘어가는 과정의 transition
을 통해 배너가 슬라이딩 되는 것을 인지한다.
하지만 아래와 같이 가짜 배너 1번이 화면 중앙에 위치해 있을 때 transition
을 제거해주고 원래 진짜 1번의 위치로 이동시키면 트랜지션 효과도 없을 뿐더러 같은 그림에서 같은 그림으로 변경되기에 우리는 배너의 변화를 눈으로 알아챌 수 없다.
따라서 아래 그림에서와 같이, 진짜 4번 → 가짜 1번으로의 이동이 끝난 시점(transitionend
)에 transition
을 제거한 뒤 -> 진짜 1번의 위치로 이동하게 되면, 사람의 눈으로 봤을 때 그대로 1번에 고정되어있는 것과 같은 착각을 일으킨다. 따라서 이 방법을 사용하면 슬라이드가 끊기지 않고 계속 연결되며 슬라이딩 되는 것과 같은 효과를 줄 수 있는 것이다.
각 배너들이 담길 Carousel을 만든다
1 | // 기본 구성은 이하와 같다. main이라는 큰 틀 안에 carousel을 만들어주고, 그 안에 각자 이미지 배너들을 넣어주면 된다. |
위치 조정
위에서 미리 짜둔 구조에 맞춰 이미지를 넣고
overflow:hidden
을 해주면 이와 같은 모양새가 나온다.
하지만 이는 정렬이 되지 않은 날 것의 상태이기 때문에transform:translateX()
를 통해 위치를 조정해줘야 한다.
이런 초기값에서
우리가 바라는 디폴트 값은 이와 같은 형태로 정렬된 상태여야 한다.
이를 위해선 transform:translateX()
를 통해 얼만큼 움직여야 원하는 배너가 중앙에 위치할 수 있는지 계산해줘야 한다.
거리 계산 방법 (지극히 주관적)
우선, 좌측 끝에서 중앙에 위치시키고 싶은 배너의 좌측 끝부분 까지의 거리를 구한다.
그리고 해당 배너가 중앙에 위치하게 된다면 남게 될 좌측 공백의 거리를 계산한다.
이제 두 값을 빼면 transform
을 통해 초기에 움직여야 하는 거리가 계산된다.
종합적인 그림 예시로 다시 요약을 하자면…
왼쪽끝 ~ 중앙에 위치하길 바라는 배너의 좌측 끝 (BannerWidth + margin
)에서 해당 배너가 중앙에 위치했을 때 남는 좌측 공백값을 빼주면 얼만큼 이동해야 배너가 중앙에 위치하는지 계산할 수 있다.
그럼 이제 슬라이딩을 어떻게 구현하면 될까?
우선 슬라이드를 움직일 버튼 두 개를 만들고, 각 버튼의
onClick
이벤트에 함수를 걸어준다.
1 | // mdArrow는 방향표시 svg react icons이므로 크게 신경 쓸 필요 없다. |
moveLeft와 moveRight함수의 코드 로직
우선, 현재 가운데에 위치해 있는 배너가 몇 번째 배너인지 체크하기 위한
currentIndex
state가 필요하다.
그리고 필자는 추가적으로 얼만큼 움직여야 하는지를 css에 전달해 줄 distance
, 그리고 transition
값을 css에 전달해 줄 timing
이라는 state도 추가해 활용했다.
1 | const moveLeft = () => { |
1 | // SCSS에서 state를 이하와 같이 전달받아 활용했다. |
슬라이드가 끝에 닿았을 때의 코드 로직 (중요)
이제
transition
값을none
으로 지정해준 뒤, 가짜 배너에서 진짜 배너로 이동시켜주는 눈속임을 행해야 할 때다.
1 | // 슬라이더 안에 props로써 distance, timing 들을 넣어준다. |
이제 onTransitionEnd
에 의해 실행되는 함수 handleFlip
코드를 작성해주면 된다.
예를 들어 가짜 9번으로 이동이 끝났을 때 (좌측이동) 진짜 9번으로 트랜지션 없이 이동하면 된다.
진짜 1번 → 가짜9번으로의 이동이 완전히 끝났을 때 트랜지션을 제거하고 눈속임을 줘야하기 때문에 onTransitionEnd
에 함수를 걸어준 것이다.
1 | const handleFlip = () => { |
React 슬라이딩 캐러셀 만드는 법 (Slider, Carousel)