캐러셀 - kowoohyuk/fe-w3-shopping GitHub Wiki

캐러셀 (Carousel) 구현하기

라이브러리로만 쓰던 캐러셀을 구현하며 여러 시행착오를 거쳤습니다!
어떻게 설계했고, 구현했는지에 대해서 늦게나마 정리해보았습니다.

1. html

현재 사용자에게 보여주고 있는 이미지를 제외한 이미지는 숨김 처리가 필요합니다.
그러므로 제가 구현하는 캐러셀의 가장 바깥에는 wrapper 가 필요하며, 이 태그는 overflow: hidden 이 핵심이 됩니다.

wrapper

wrapper--------------------------------------  
|                                           |
|                                           |
|                                           |
|                                           |
|                                           |
---------------------------------------------
wrapper {
 overflow: hidden;
}

다음으로 캐러셀 태그들을 감싸는 제 2의 wrapper인 box 가 필요합니다.
얼핏보면 위의 wrapper와 중복되는 역할로 보이지만 이 태그는 바깥의 태그와는 다르게 overflow 가 visible 입니다.
box의 하위 태그들의 width의 합 만큼 width 가 증가해야 합니다.

wrapper + box

wrapper--------------------------------------  
| box-------------------------------------- |
| |                                       | |
| |                                       | |
| |                                       | |
| ----------------------------------------- |
---------------------------------------------
wrapper {
 overflow: hidden;
}
box {
 overflow: visible; // 기본 값
 width: 100 * 캐러셀 태그의 개수
}

이제 캐러셀 태그 item 을 박스 태그의 내부에 추가합니다.
총 3개를 추가하겠습니다.

wrapper + box + item

wrapper--------------------------------------  
| box-------------------------------------- |
| | item-----  item-----  item-----       | |
| | |       |  |       |  |       |       | |
| | ---------  ---------  ---------       | |
| ----------------------------------------- |
---------------------------------------------
wrapper {
 overflow: hidden;
}
box {
 overflow: visible; // 기본 값
 width: 300%; // 3개의 캐러셀 태그
}
item {
 float: left;
 width: 100 / 캐러셀 태그의 개수
}

마지막으로 슬라이드를 이동할 수 있는 네비게이션 버튼 button 이 필요합니다.
button은 이전, 다음 으로 이동할 수 있게 2개가 필요합니다.

wrapper + box + item + arrow

wrapper--------------------------------------  
| box-------------------------------------- |
| | item-----  item-----  item-----       | |
| | |       |  |       |  |       |       | |
| | ---------  ---------  ---------       | |
| ----------------------------------------- |
| button---    button---                    |
| |       |    |       |                    |
| ---------    ---------                    |
---------------------------------------------
wrapper {
 overflow: hidden;
}
box {
 overflow: visible; // 기본 값
 width: 300%; // 3개의 캐러셀 태그
}

위의 형태가 제가 만든 캐러셀의 html 구조입니다.
코드펜을 사용하여 코드를 확인할 수 있습니다.


2. 슬라이드

슬라이드의 이동효과를 주기 위한 효과는 transitiontransform 을 사용합니다.

box {
  ...
  transition: transform 0.3s linear;
  transform: translateX();
}

버튼을 눌렀을 때, 다른 item을 보여주는 발생하는 흐름은 아래와 같습니다.

  1. 버튼을 클릭한다.
  2. box를 버튼이 가리키는 방향으로 transform 처리
  3. box 내부의 item의 순서 바꿔주기.
  4. box의 transform 를 원래의 값으로 변경

버튼 이벤트

// 1. 버튼을 클릭
button.addEventListener('click', () => {
  // 2. 버튼이 가리키는 방향으로 transform
  box.style.transform = 'translateX(abc)';
  // 3. box 내부의 item의 순서 바꿔주기
  box.insertBefore(box.lastElementChild, box.firstElementChild);
  // 4. box의 transform 를 원래의 값으로 변경
  box.style.transform = 'translateX(기존 값)';
});

여기서 2번 이후의 처리에 딜레이를 주지 않게 되면 애니메이션이 발생하지 않게 되므로 setTimeout을 통하여 transition과 동일한 딜레이를 추가해야 합니다.
또한, 4번이 실행되는 시점에서 transition이 켜져있다면 box가 원위치로 되돌아가는 슬라이드가 발생하므로 transition의 on, off가 필요합니다.

추가 사항을 포함하여 구현한 코드

위의 코드에서 두 번째 위치하는 item이 첫 번째 item처럼 보이게 됩니다.
이는 렌더링 직후 위치 바꿈을 통해 해결 할 수 있습니다.

init() {
  ...
  box.insertBefore(box.lastElementChild, box.firstElementChild);
}
init();