javascript로 carousel slide 구현해보기

Jungwon Lee(Jenny)·2021년 2월 25일
3
post-thumbnail

Carousel 구현로직

우선 html 코드와 css는 이런 상태로 시작했습니다:

HTML코드 :

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Transition Practice</title>
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <div class="slide_box">
      <div class="slide_list">
        <div id="lastClone" class="slide_item">5</div>
        <div class="slide_item">1</div>
        <div class="slide_item">2</div>
        <div class="slide_item">3</div>
        <div class="slide_item">4</div>
        <div class="slide_item">5</div>
        <div id="firstClone" class="slide_item">1</div>
      </div>
    </div>
    <button class="prevBtn">prev</button>
    <button class="nextBtn">next</button>
    <script src="transition.js"></script>
  </body>
</html>

CSS 코드:

.slide_box {
  margin: 500px 0 0 700px;
  border: rgb(255, 14, 135) 3px dotted;
  width: 100px;
  height: 100px;
  /* overflow: hidden; */
}

.slide_item {
  background-color: rgb(255, 215, 187);
  width: 100px;
  height: 100px;
  text-align: center;
  line-height: 100px;
  font-size: larger;
  border: rgb(165, 165, 165) 0.5px solid;
}
.slide_list {
  width: 900px;
  display: flex;
  height: 100px;
}

button {
  margin-left: 610px;
}

image

연습용이라 css를 대충 지정했습니다..😂

일단 slide_box에 overflow:hidden을 주지 않고 진행이 어떻게되나 확인하면서 시작했습니다.

overflow:hidden을 주면,

image

이렇게 slide_box위치만 똮! 하고 보입니다..!!

의문점: 왜 5부터 시작했나. 1, 2, 3, 4, 5 이렇게 진행되는데???

transition을 줄 때 자연스럽게 넘어가게 하기 위해서 마지막 슬라이드인 5번을 앞에 추가하고,

맨 앞의 1번 슬라이드를 맨 뒤에 하나 추가했습니다.

나중에 javascript 코드 설명때 더 쉽게 알수있지만,

translateX()로 한 슬라이드 크기당 움직이다가, 마지막 5번 슬라이드에 다다르면

다시 맨 앞으로 이동시켜야하는데, 이때 옆으로 넘기는거보다 슈루룩 하고 앞으로 이동하는?느낌이 들어서 이걸 어떻게 해결하나 싶었습니다.


그래서 참고한 동영상을 보니 저렇게 마지막슬라이드와 첫번째슬라이드를 끝에 추가하고 js코드로 어찌어찌 설정을 하면 자연스럽게 넘어가게 할수 있습니다.

이제 js코드를 살펴보면,

const carouselSlide = document.querySelector(".slide_list");
const carouselContents = document.querySelectorAll(".slide_item");

const prevBtn = document.querySelector(".prevBtn");
const nextBtn = document.querySelector(".nextBtn");

//counter
let counter = 1;
const size = carouselContents[0].clientWidth;

carouselSlide.style.transform = "translateX(" + -size * counter + "px)";

일단 document.querySelector을 사용하여 js코드 필요한 요소들을 불러오고,

몇번째 slide에 와있는지를(index개념) 알수있도록 counter을 만들었습니다.

counter에 1을 준 이유는 html구조상 5->1->2->3->4->5->1 이렇게 되어있기에,
carouselSlide.style.transform = "translateX(" + -size * counter + "px)";
이 코드를 통해서 왼쪽으로 슬라이드 width만큼 사전에 먼저 움직여줍니다.

image

그럼 이런 상황이 됩니다.

나머지 코드를 살펴보면,

//Button Listeners
nextBtn.addEventListener("click", () => {
  if (counter >= carouselContents.length - 1) return;
  carouselSlide.style.transition = "transform 0.3s ease-in-out";
  counter++;
  carouselSlide.style.transform = "translateX(" + -size * counter + "px)";
});

prevBtn.addEventListener("click", () => {
  if (counter <= 0) return;
  carouselSlide.style.transition = "transform 0.3s ease-in-out";
  counter--;
  carouselSlide.style.transform = "translateX(" + -size * counter + "px)";
});
console.log(carouselContents.length);

이전 버튼, 그리고 다음버튼에 클릭이벤트를 달아주는 코드입니다.
if (counter >= carouselContents.length - 1) return; 이 코드와 if (counter <= 0) return; 이 코드를 달게된 이유는 나중에 자세히 설명하겠습니다.

(-size*counter) 만큼이 왼쪽으로 이동하는 길이입니다.


carouselSlide.addEventListener("transitionend", function () {
  if (carouselContents[counter].id === "lastClone") {
    carouselSlide.style.transition = "none";
    counter = carouselContents.length - 2;
    carouselSlide.style.transform = "translateX(" + -size * counter + "px)";
  }
  if (carouselContents[counter].id === "firstClone") {
    carouselSlide.style.transition = "none";
    counter = carouselContents.length - counter;
    carouselSlide.style.transform = "translateX(" + -size * counter + "px)";
  }
});

요기가 대망의 transitionend를 써본 코드인데...

if (carouselContents[counter].id === "lastClone")
이 코드의 의미는, 아까 위의 html에서 querySelectorAll로 불러온 슬라이드 노드리스트들이

carouselContents변수 안에 하나씩 담겨있고, 그걸 index로 접근한 것이다.

만약 사용자가 계속 이전 버튼을 클릭하다가

counter이 0이 되어서 맨 앞에 추가해둔 <div id="lastClone" class="slide_item">5</div>에 도달하면,

carouselSlide.style.transition="none";을 설정해서 움직여도 아무런 애니메이션 효과가 없도록 설정하고

counter=carouselContents.length - 2;를 적용하고

carouselSlide.style.transform = "translateX(" + -size * counter + "px)"; 를 실행시켜서
image

이 위치로 아무 애니메이션 없이 이동하도록 설정한다.

반대로 비슷한 로직으로 다음버튼을 계속 누르다가 counter이 마지막 slide의 인덱스와 같게되면

counter = carouselContents.length - counter;
carouselSlide.style.transform = "translateX(" + -size * counter + "px)";

이렇게 작성해서

image

여기로 돌아오게 하면 된다.

counter = carouselContents.length - counter;

이거 말고 그냥 counter=1; 이라고 써도 됩니다.

car1

일단 이렇게 작동합니다. 이상태에서 overflow:hidden을 주면

car2

요로코롬 작동합니다!!!!

아까 설명하려던 버튼 이벤트쪽 코드

//Button Listeners
nextBtn.addEventListener("click", () => {
  if (counter >= carouselContents.length - 1) return;
  carouselSlide.style.transition = "transform 0.3s ease-in-out";
  counter++;
  carouselSlide.style.transform = "translateX(" + -size * counter + "px)";
});

prevBtn.addEventListener("click", () => {
  if (counter <= 0) return;
  carouselSlide.style.transition = "transform 0.3s ease-in-out";
  counter--;
  carouselSlide.style.transform = "translateX(" + -size * counter + "px)";
});
console.log(carouselContents.length);

여기서 만약 if 부분들을 주석처리하고 실행할때, transition이 0.3초만에 휙 움직이는 속도보다 사람의 클릭속도가 빠르면 왼쪽,오른쪽으로 무한이동한다..

요로케...
car4

그래서 버튼클릭 이벤트로는 counter이 0이거나 0보다 작을때 아무것도 하지않고return하도록 조건을 걸어줘야한다.ㅠㅠ

반대의 경우도 똑같은 로직으로 if문을 걸어주면 된다...

profile
FE개발자가 되고싶은 말하는 감자

0개의 댓글