막막함으로 설계조차 못 하고 있었을 때, 흔쾌히 구현방법을 공유해준 멋찐 이브에게 고마움을 표현하며 🌷
간단하게 필요한 구성을 나열해보면 아래와 같다:
1) 사용자가 보게 될 창문 역할을 하며 하나의 엘리먼트 외에는 보이지 않게 가려주는 window
2) 여러 엘리먼트를 내부에 담고 있을 container
3) 각각의 요소를 나타내는 cell
4) 사용자가 동작을 컨트롤 할 수 있게 API역할을 하는 previous 버튼과 next 버튼
DOM으로 previous버튼과 next버튼에 해당하는 요소를 가지고 온 다음,
addEventListener()
메서드로 콜백함수를 실행해 줄 클릭 이벤트를 건다.
//ex.
const prevBtn = document.querySelector(".prev");
const nextBtn = document.querySelector(".next");
function addEvent(){
prevBtn.addEventListener('click', 콜백함수);
nextBtn.addEventListener('click', 콜백함수);
};
이제 콜백함수를 만들어야 하는데,
가장 먼저 선택된 방향으로 컨테이너가 밀리는 듯한 움직임을 실행시켜야 한다.
여기서는 요소에 회전, 크기 조절, 기울이기, 이동 효과 더해주는 transform
속성을 이용한다.
transform
은 굉장히 다양한 값들을 가지고 있지만(matrix, rotate, skew, scale, etc.)가로로 이동하는 효과는 transform: translateX(이동거리)
를 이용해 구현할 수 있다.
JS를 통해 동적으로 추가할 때는 노드.style.transform = translateX(이동거리)
의 형식을 사용한다.
⭐️⭐️⭐️ transform
의 경우, classList.add(클래스명)
보다 인라인(element.style.속성()
의 형식)으로 적용하는 것이 더 잘 동작한다.⭐️⭐️⭐️
//ex.
const container = document.querySelector(".container");
container.style.transform = `translateX(${direction * (100 / 요소의 갯수)}%)`;
이 때, transitionDuration
속성을 지정해주면 실행되는 시간을 설정해 보다 부드러운 애니메이션을 구현한다.
//ex.
container.style.transitionDuration = '500ms';
지정해준 transform
실행시간이 끝나면 컨테이너는 원래 있던 자리로 돌아와야 한다.
(중요) 마지막 요소까지 밀릴 경우 끝이 나는 것이 아니라, 다시 가장 앞에 있던 요소가 나와야 하기 때문에 컨테이너는 제자리에 두고 컨테이너 안 요소들을 꺼내서 순서를 바꿔주어야 하는 것이다❗️
사용자가 보기에는 컨테이너가 움직이는 것처럼 보여져야 하기 때문에 transform
실행이 완료되는 즉시 transform
이 적용된 스타일을 removeAttribute
로 취소한다.
이 때는 ontransitionend
메서드를 사용할 수 있다.
//ex.
container.ontransitionend = () => {요소의 순서를 바꿔주는 콜백함수};
// 콜백 함수 내에 container.removeAttribute('style'); 를 추가하기
요소의 순서를 바꿔주는 콜백함수는,
next버튼이 눌린 경우 => 맨 앞의 요소를 떼어서 맨 뒤에 붙인다. (appendChild
사용)
previous버튼이 눌린 경우 => 맨 뒤의 요소를 떼어서 맨 앞으로 붙인다.(insertBefore
사용)
두 가지를 모두 설정해줘야 한다.
//ex.
function transitionEndCallBack(selectedBtn) {
container.removeAttribute('style');
(selectedBtn === 'prev') ?
container.insertBefore(container.lastElementChild, container.firstElementChild)
: container.appendChild(container.firstElementChild);
}
⭐️⭐️⭐️ 이 때 주목해야 할 점은, appendChild나 insertBefore은 중복으로 추가되는 것이 아니라 원래 있던 자리에서 빠져나와 지정된 자리로 옮겨간다는 것이다.⭐️⭐️⭐️
이제 로직이 다 구현되었으니 컨테이너를 감싸고 있는 window에 overflow:hidden
속성(CSS)을 적용해주면 우리가 알고 있는 캐러셀 슬라이더의 모습을 볼 수 있다!
<overflow:hidden 적용 전>
window: red
container: green
cell: pink
<overflow:hidden 적용 후>
appendChild도 중복노드가 허용이 안되는 줄 몰랐네요. 저는 insertBefore(firstNode, null) 이런식으로 했는데, 몰랐던 사실을 또 하나 배워갑니다. mini carousel 이모지 넘 귀엽네여 ㅎㅎㅎ