carousel : 번역 시 회전목마라는 뜻으로 슬라이드쇼와 같은 방식으로 콘텐츠를 표시하는 UX 구성 요소를 의미
- carousel은 다양한 종류가 있음
- 플러그인을 사용하면 쉽게 구현할 수 있다.
(owl-carousel, bootstrap-carousel, swiper-carousel 등)
수업에서 배운 perspective 속성과 perserve-3d 속성을 응용하여 3d-carousel를 직접 구현해 보기
구현 포인트
- prespective 속성과 preserve-3d 속성
- transformZ 길이 적용
<div class="carousel"> <div class="carousel-card">Card1</div> <div class="carousel-card">Card2</div> <div class="carousel-card">Card3</div> <div class="carousel-card">Card4</div> <div class="carousel-card">Card5</div> <div class="carousel-card">Card6</div> <div class="carousel-card">Card7</div> <div class="carousel-card">Card8</div> <div class="carousel-card">card9</div> </div>
<div class="scene"> <div class="carousel"> <div class="carousel-card">Card1</div> <div class="carousel-card">Card2</div> <div class="carousel-card">Card3</div> <div class="carousel-card">Card4</div> <div class="carousel-card">Card5</div> <div class="carousel-card">Card6</div> <div class="carousel-card">Card7</div> <div class="carousel-card">Card8</div> <div class="carousel-card">card9</div> </div> </div>
.scene { width: 210x; height: 140px; position: relative; /* 원근감을 위해 */ perspective: 1800px; margin: 0 auto; margin-top: 100px; }
.carousel { width: 100%; height: 100%; position: absolute; /* perspective가 적용된 자식 요소들에 3D 효과 원근감*/ transform-style: preserve-3d; transition: all .5s; }
.carousel-card {
position: absolute;
/* 셀 배치를 약간씩 떨어뜨림*/
width: 190px;
height: 120px;
left: 10px;
top: 10px;
transition: all .5s;
font-size: 30px;
color: #fff;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
}
angle
=360 / carousel-card 개수
.carousel-card:nth-child(1) { transform: rotateY( 0deg); }
.carousel-card:nth-child(2) { transform: rotateY( 40deg); }
.carousel-card:nth-child(3) { transform: rotateY( 80deg); }
.carousel-card:nth-child(4) { transform: rotateY(120deg); }
.carousel-card:nth-child(5) { transform: rotateY(160deg); }
.carousel-card:nth-child(6) { transform: rotateY(200deg); }
.carousel-card:nth-child(7) { transform: rotateY(240deg); }
.carousel-card:nth-child(8) { transform: rotateY(280deg); }
.carousel-card:nth-child(9) { transform: rotateY(320deg); }
r 만큼의 길이를 transformZ 속성을 주어 carousel-card를 떨어뜨린다.
.carousel-card:nth-child(1) { transform: rotateY( 0deg) translateZ(288px); } .carousel-card:nth-child(2) { transform: rotateY( 40deg) translateZ(288px); } .carousel-card:nth-child(3) { transform: rotateY( 80deg) translateZ(288px); } .carousel-card:nth-child(4) { transform: rotateY(120deg) translateZ(288px); } .carousel-card:nth-child(5) { transform: rotateY(160deg) translateZ(288px); } .carousel-card:nth-child(6) { transform: rotateY(200deg) translateZ(288px); } .carousel-card:nth-child(7) { transform: rotateY(240deg) translateZ(288px); } .carousel-card:nth-child(8) { transform: rotateY(280deg) translateZ(288px); } .carousel-card:nth-child(9) { transform: rotateY(320deg) translateZ(288px); }
=> css 대신 javascript를 이용하여 carousel-card 배치를 동적으로 할당
const carouselCard = documnet.queryselector(".carousel-card"); const rataeAngle = 360 / carouselCard.length; const radian = (ratateAngle / 2) * Math.PI / 180; const tz = (210 / 2) / Math.tan(radin); carouselCard.forEach((el,idx)=>el.style.transform = `rotateY(${ratateAngle*idx}deg) translateZ(${tz}px)`);
📌 r를 구하는 방법 => 삼각비를 이용한다.
- r = (밑변의 길이) / tan(angle)
- 여기서 구하려는 r = (card의 width / 2 ) / Math.tan(angle에 해당하는 radian)
- radian = (angle / 2) * (Math.PI / 180)
casrousel angle
=angle
*현재 카드의 index
- carousel, carousel-card 들의 translate 축 변경
- X축으로 회전시
transform = translateY()
=>transform = translateX()
로 변경- Y축으로 회전시
transform = translateX()
=>transform = translateY()
로 변경- r 길이가 바뀌어야함 => r = (card-height / 2) / Math.tan(Radin)
- X축으로 회전 시
card-width 값 대신 card-height 값 대입- Y축으로 회전 시
card-height 값 대신 card-width 값 대입- classList row 확인을 통해 축을 구분해줌
최종 코드