본문 바로가기
공부/javascript

2022.07.21 - 무한 슬라이드 구현

by 기묜몬 2022. 7. 21.

프로젝트때 슬라이드 구현에 꽤나 애를 먹었던 기억이 있었다.

이번에는 좀 완벽하게 해보고 싶어서 구글링 참고하여 가로 길이 맞춰 구현해봤다!

역시 하고나면 뿌듯해~~

 

* 01 ~ 05 까지 총 다섯개의 이미지 무한루프

[ 중요 포인트 !! ]

1. li를 클론하여 앞뒤로 복사해준다 ( classList 이용해서 "clone" 클래스 추가 )

2. 슬라이드로 보여줄 li 너비를 설정하고

3. ul과 li를 감싸고 있는 wrapper에 position relative를 설정

4. 슬라이드로 보여줄 li에 position absolute 설정

5. 슬라이드를 부드럽게 전환시켜 줄 transition이 포함된 css 클래스 추가해주기 (나중에 js에서 classList로 추가해서 전환효과 줄것)

6. clone 함수 생성 / makeClone()

7. 전체 너비를 구해서 ul의 너비를 지정하는 함수 생성 / updateWidth()

8. 초기 위치를 잡는 함수 생성 / setinit()

9. 버튼 클릭시 슬라이드 이동 함수 생성 

10. 슬라이드 마지막에서 처음으로 바로 넘어가는 과정 숨기기  / moveSlide

 

 

[ 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" />
    <link rel="stylesheet" href="./loopCSS.css" />
    <title>Document</title>
  </head>
  <body>
    <div class="slide_wrapper">
      <ul class="slides">
        <li>  01  <img  src="https://i.pinimg.com/564x/88/31/c6/8831c6628b6a3fb79db75b39d8ef98d6.jpg" alt=""/> </li>
        <li>  02  <img  src="https://i.pinimg.com/564x/88/31/c6/8831c6628b6a3fb79db75b39d8ef98d6.jpg" alt=""/> </li>
        <li>  03  <img  src="https://i.pinimg.com/564x/88/31/c6/8831c6628b6a3fb79db75b39d8ef98d6.jpg" alt=""/> </li>
        <li>  04  <img  src="https://i.pinimg.com/564x/88/31/c6/8831c6628b6a3fb79db75b39d8ef98d6.jpg" alt=""/> </li>
        <li>  05  <img  src="https://i.pinimg.com/564x/88/31/c6/8831c6628b6a3fb79db75b39d8ef98d6.jpg" alt=""/> </li>
      </ul>
    </div>

    <p class="controls">
      <span class="prev">prev</span>
      <span class="next">next</span>
    </p>

    <script src="./loopSlide.js"></script>
  </body>
</html>

 

[ CSS ]

* {
  margin: 0;
  padding: 0;
}
img {
  width: 100%;
  height: 100%;
}

li {
  list-style: none;
}
.slide_wrapper {
  position: relative;
  width: 990px;
  margin: 0 auto;
  height: 300px;
  overflow: hidden;
}
.slides {
  position: absolute;
  left: 0;
  top: 0;
}
.slides.animated {
  transition: 0.5s ease-out;
}
.slides li {
  margin-top: 10px;
  float: left;
  width: 300px;
  height: 300px;
}
.slides li:not(:last-child) {
  margin-right: 30px;
}
.controls {
  text-align: center;
  margin-top: 50px;
}
.controls span {
  background-color: #333;
  color: #fff;
  padding: 10px 20px;
  margin: 0 10px;
  cursor: pointer;
}

 

[ JS ]

let slides = document.querySelector(".slides"),
  slide = document.querySelectorAll(".slides li"),
  currentIdx = 0,
  slideCount = slide.length,
  slideWidth = 300,
  slideMargin = 30,
  prevBtn = document.querySelector(".prev"),
  nextBtn = document.querySelector(".next");

makeClone();

function makeClone() {
  for (let i = 0; i < slideCount; i++) {
    let cloneSlide = slide[i].cloneNode(true);
    cloneSlide.classList.add("clone");
    slides.appendChild(cloneSlide);
  }
  //index 번호 4번은 슬라이드 05임
  //  slideCount -1 초기값
  for (let i = slideCount - 1; i >= 0; i--) {
    let cloneSlide = slide[i].cloneNode(true);
    cloneSlide.classList.add("clone");
    // 원래 있던 내용 앞에 추가해야함(요소의 앞)
    slides.prepend(cloneSlide);
  }

  updateWidth();
  setinit();
  setTimeout(function () {
    slides.classList.add("animated");
  }, 100);
}

// 전체 너비를 구해서 ul의 너비를 지정하는 함수
function updateWidth() {
  let currentSlides = document.querySelectorAll(".slides li");
  let newSlideCount = currentSlides.length;

  let newWidth =
    (slideWidth + slideMargin) * newSlideCount - slideMargin + "px";
  slides.style.width = newWidth;
}

//초기 위치 잡는 함수
function setinit() {
  // 왼쪽으로 움직일거니까 ( - )붙임
  // 이동할 변수
  let TranslateValue = -(slideWidth + slideMargin) * slideCount;
  slides.style.transform = "translateX(" + TranslateValue + "px)";
}

nextBtn.addEventListener("click", function () {
  // 지금 보고있는 슬라이드 수 +1 로 이동
  moveSlide(currentIdx + 1);
});
prevBtn.addEventListener("click", function () {
  // 지금 보고있는 슬라이드 수 +1 로 이동
  moveSlide(currentIdx - 1);
});

// 숫자가 넘어와야 함수가 작동 하도럭
// next 누를수록 왼쪽으로 translate left 값이 거리만큼 이동해야함
// 전체가 슬라이드 너비+여백 만큼 이동해야지?
function moveSlide(num) {
  // 원래는 0이었는데 사용자가 이동하면 index가 1로 바뀌어있어야 함
  slides.style.left = -num * (slideWidth + slideMargin) + "px";
  //이동한 다음에는 currentIdx를 반드시 슬라이드가 최종적으로 보고있는 num 숫자만큼 바껴있어야 함.
  currentIdx = num;
  console.log(currentIdx, slideCount);
  // 마지막이면 1번으로 다시 돌리기

  if (currentIdx == slideCount || currentIdx == -slideCount) {
    setTimeout(function () {
      slides.classList.remove("animated");
      slides.style.left = "0px";
      currentIdx = 0;
    }, 500);

    setTimeout(function () {
      slides.classList.add("animated");
    }, 600);
  }
}

 

[ 배운 것 ]

1. cloneNode 

function makeClone() {
  for (let i = 0; i < slideCount; i++) {
    let cloneSlide = slide[i].cloneNode(true);
    cloneSlide.classList.add("clone");
    slides.appendChild(cloneSlide);
  }

cloneNode()는 엘리먼트를 DOM에 복제하여 붙여넣기를 하면 동일한 기능을 수행하므로 코드를 간결하고 쉽게 만들 수 있다. 

 

2. 변수 선언해서 li 너비 구하기 

  (slideWidth + slideMargin) * newSlideCount - slideMargin + "px";

변수로 width, margin 값 지정해두고 슬라이드 개수와 px 값 더해서 너비 구하는 것 신기했다.

저번에 css 속성값 변경하는 실습에서 했었는데 두번하니 더 기억에 남을 듯 하다.