- 코드
- 코드 구현 설명
슬라이더를 구현하기 위해서는 다섯가지 슬라이더 블록을 한 곳에 모두 겹치게 하여 .active
, .prev
, .next
에 각각 css 스타일링을 부여하여 구현할 수 있다.
.active
: 겹쳐지는 다섯가지 슬라이드 중 유일하게 보여지는 블록이다. 따라서 안 보여지는 4가지 블록의 투명도 속성(opacity
)를 0으로 두고 .active
속성을 가진 블록만 투명도 속성(.opacity
)를 1로 두어 구현할 수 있다. 추가적으로 z-index와 opacity에도 transform액션을 주어서 좀 더 동적인 UI를 구성하였습니다.
.prev
: .active
속성 이전의 블록을 나타냅니다. 넘겨주는 css 전환을 주기 위해 다음과 같은 속성을 주었습니다.
transform : translateX(100%); // prev
.next
: .active
속성의 다음 블록을 나타냅니다. 넘겨주는 css 전환을 주기 위해 다음과 같은 속성을 주었습니다.
transform : translateX(-100%)' // next
평소 div를 나란히 작성하게 되면 세로 일렬로 줄세우기를 하게 된다. 왜냐하면 position : relative
가 기본값이기 때문
따라서 각 겹치게 하기 위한 슬라이더 블록
<div class = "carousel_item"></div>
들의 속성을 position = absolute
로 설정해주면 이를 해결 할 수 있다.
제가 평소에 많이 쓰는 가운데 정렬의 경우 다음과 같다.
display : flex;
justify-content : center;
align-items : center
상위 태그를 다음과 같이 작성하고 하위 태그에 position :absolute를 할 경우 content가 가운데 정확히 놓여지지 않고 블록이 가운데 지점부터 시작하는 것을 알 수 있다.
이를 해결하기 위해
가로 정렬을 다음과 같이 하였다.
width : 90%;
min-height: 100vh;
margin : auto;
그리고 세로 정렬을 내가 넣고자하는 div의 height값을 구하여 이를 전체 세로 길이의 절반(50vh)에서 빼주어 위치를 조정하였습니다.
position: relative; // 하위 태그의 position :absolute 설정을 위해
top: calc(50vh - 100px);
버튼을 누를 때마다 currentId
값이 상승, 하강함에 따라 이에 따른 prev, current, next값의 인덱스를 계산하여 각각의 속성을 부여하는 방식으로 구현하였습니다.
// active, next, prev 할당 함수
this.assignActiveNextPrev = () => {
const { currentId, carouselListLength } = this;
const current =
currentId < 0
? (carouselListLength + (currentId % 5)) % 5
: currentId % 5;
const prev = current === 0 ? carouselListLength - 1 : (current - 1) % 5;
const next = current === carouselListLength ? 0 : (current + 1) % 5;
return { newPrev: prev, newCurrent: current, newNext: next };
};
추가적으로 각각의 클래스에게 부여하고 다음 이벤트가 들어왔을 시 이를 리셋하고 새로 구한 prev, current, next 값에 따라 그에 맞는 태그에 클래스 속성을 부여해야 합니다.
첫번째 방법
모든 태그 리스트를 반복문을 돌리면서 각각의 클래스명을 부여하는 방식
carouselItemList.forEach((carouselItem, idx) => {
switch (idx) {
case prev:
carouselItem.className = carouselItemClassName + " prev";
break;
case current:
carouselItem.className = carouselItemClassName + " active";
break;
case next:
carouselItem.className = carouselItemClassName + " next";
break;
default:
carouselItem.className = carouselItemClassName;
}
});
다음과 같이 코드를 짤 경우 엄청나게 많은 슬라이더 양이 있을 경우 이에 따른 성능 저하가 고려되어졌습니다.
따라서 저는 두번째 방법을 생각해 보았습니다.
두번째 방법
버튼 이벤트 동작 시 이전 인덱스 (prev, current, next)를 제거하고 새로 구한 인덱스(newPrev, newCurrent, newNext)를 구하고 이를 추가하는 식으로 구현하였습니다.
// active, next, prev 설정하여 보여줄 Carousel화면 결정
this.showCarouselItem = () => {
const { prev, current, next } = this;
// active 설정이 있을 경우
if (![prev, current, next].includes(null)) {
// active 설정 삭제
this.addOrRemoveActiveClassName({ prev, current, next }, removeClassName);
}
// active 설정을 위한 index 계산
const { newPrev, newCurrent, newNext } = this.assignActiveNextPrev();
// active 설정 추가
this.addOrRemoveActiveClassName(
{ prev: newPrev, current: newCurrent, next: newNext },
addClassName
);
this.prev = newPrev;
this.current = newCurrent;
this.next = newNext;
};
carouselItem.className = carouselItemClassName + " prev";
break;
case current:
carouselItem.className = carouselItemClassName + " active";
break;
case next:
carouselItem.className = carouselItemClassName + " next";
위와 같은 구문을 리터럴을 사용하여 적용시키자
index 로직할당 구현 변경
더러운 코드를 갈아 엎자
슬라이드 클릭 시 애니메이션 변경
오른쪽 클릭 시 -100%
왼쪽 클릭 시 +100%