JavaScript : Slide Animation

Study/JavaScript

2022.12.07.

  • UI/UX 반응형 웹디자인&웹퍼블리셔 개발자 과정 - DAY 59



Review


 오늘 배운 건 솔직하게 정말 하나도 이해하지 못했다.

선생님께서는 이게 정말 프론트엔드 개발이라고 하시던데 아직 나는 공부가 더 많이

필요할 것 같다는 생각을 했다.

오늘 것은 아직 이해를 못해도 된다고 말씀하셨지만 걱정이 태산이다. 흑흑

내일부터는 jQuery로 들어간다고 하시는데 큰일났당... 나머지 공부를 해야겠다 ㅠ_ㅠ

주석을 달아가면서 이해를 하려고 해봤으나 천천히 더 공부를 해야할 것 같다.

 

요새는 일을 마치고 GTQ 시험을 준비하느라 정신이 없다. 

시험이 3주도 채 남지 않아서 바쁘당. 시험이 끝나면 니꼬쌤의 클론코딩을 해보려고 한다.

그래도 나는 코딩이 재밌어서 다행이다... 힘들더라도 해내고야 말아야지 !

 

파이팅-

 

 

 


 

  • UI/UX 반응형 웹디자인&웹퍼블리셔 개발자 과정 - DAY 59

 

<첫 번째 예제>

 

 

- HTML

 

    <div class="container">
      <ul>
        <div class="numbertext">
          <span id="slide_start"></span> 
          / <span id="slide_end"></span>
        </div>
        <li class="slide">
          <img src="../../마이페이지/img/window.jpg" alt="window" />
          <div class="text">
            <span>1</span>
            <span>3</span>
          </div>
        </li>
        <li class="slide">
          <img src="../../마이페이지/img/trip.jpeg" alt="trip" />
          <div class="text">
            <span>2</span>
            <span>3</span>
          </div>
        </li>
        <li class="slide">
          <img src="../../마이페이지/img/pado.jpeg" alt="pado" />
          <div class="text">
            <span>3</span>
            <span>3</span>
          </div>
        </li>
      </ul>
          <a class="prev" onclick="plusSlides(-1)">&lang;</a>
          <a class="next" onclick="plusSlides(1)">&rang;</a>
      </div>
    </div>
    <div style="text-align: center">
      <span class="dot" onclick="currentSlide(1)"></span>
      <span class="dot" onclick="currentSlide(2)"></span>
      <span class="dot" onclick="currentSlide(3)"></span>
    </div>

 

 

 

- CSS

 

      @font-face {
        font-family: pretendard;
        src: url(../fontawesome-free-6.2.0-web/webfonts/Pretendard-Regular.woff)
          format("woff");
      }

      * {
        padding: 0;
        margin: 0;

        font-family: pretendard, sans-serif;
      }

      ul,
      li {
        list-style: none;
      }

      a {
        text-decoration: none;
      }

      body {
        text-align: center;

        margin-top: 50px;
      }

      .container {
        position: relative;

        max-width: 1000px;

        margin: 0 auto;
      }

      
      .numbertext {
        position: absolute;
        top: 0;

        color: #fff;
        font-size: 14px;

        margin-bottom: 30px;
        padding: 8px 12px;
      }

      .slide {
        width: 100%;
        height: 706px;

        overflow: hidden;
      }

      .slide img {
        width: 995px;
        height: 706px;

        object-fit: cover;
      }

      .slide .text {
        position: absolute;
        top: 85%;
        left: 50px;

        width: 90%;

        display: flex;
        justify-content: space-between;


        color: #fff;
        font-size: 60px;
        font-weight: bold;
      }

      .prev,
      .next {
        cursor: pointer;

        position: absolute;
        top: 50%;

        width: auto;

        padding: 20px;
        margin-top: -22px;

        border-radius: 3px;

        color: white;
        font-weight: bold;
        font-size: 25px;

        transition: 0.6s ease;
      }

      .prev {
        left: 20px;
      }

      .next {
        right: 20px;
      }

      .prev:hover,
      .next:hover {
        background-color: rgba(0, 0, 0, 0.5);
      }

      .dot {
        cursor: pointer;

        display: inline-block;
        width: 15px;
        height: 15px;

        margin: 20px 2px;

        background-color: #bbb;
        border-radius: 50%;

        transition: background-color 0.6s ease;
      }

      .active,
      .dot:hover {
        background-color: #717171;
      }

      .fade {
        animation-name: fade;
        animation-duration: 1.5s;
      }

      @keyframes fade {
        from {
          opacity: 0;
        }
        to {
          opacity: 1;
        }
      }

 

 

- JavaScript

 

    <script>
      let slideIndex = 1;
      showSlide(slideIndex);

      function plusSlides(n) {
        showSlide((slideIndex += n));  
        // slideIndex = slideIndex + n
      }

      function currentSlide(n) {
        showSlide((slideIndex = n));
      }

      setInterval(function () {
        plusSlides(1);
      }, 5000);

      function showSlide(n) {
        let slides = document.getElementsByClassName("slide");
        let dots = document.getElementsByClassName("dot");
        let len = slides.length;

        if (n > len) {
          slideIndex = 1;
        } else if (n < 1) {
          slideIndex = len;
        }

        for (let i = 0; i < len; i++) {
          slides[i].style.display = "none";
          slides[i].className = slides[i].className.replace(" fade", "");
          dots[i].className = dots[i].className.replace(" active", "");
        }

        slides[slideIndex - 1].className += " fade";
        slides[slideIndex - 1].style.display = "block";
        dots[slideIndex - 1].className += " active";

        document.getElementById("slide_start").textContent = slideIndex;
        document.getElementById("slide_end").textContent = len;

        console.log(slideIndex);
      }
    </script>

 

0

 

마우스로 클릭하지 않아도 자동으로 슬라이드가 넘어가며, 이전 / 다음 버튼을 두어 사용자가

직접 넘길 수 있는 슬라이드를 만들었다. 

 

 

 


 

 

<두 번째 예제>

 

 

- HTML

 

    <div id="slideShow">
      <ul class="slides">
        <li><img src="../../마이페이지/img/window.jpg" alt="photo1" /></li>
        <li><img src="../../마이페이지/img/trip.jpeg" alt="photo2" /></li>
        <li><img src="../../마이페이지/img/pado.jpeg" alt="photo3" /></li>
        <li><img src="../../마이페이지/img/win.jpeg" alt="photo4" /></li>
        <li><img src="../../마이페이지/img/1.jpg" alt="photo5" /></li>
        <li><img src="../../마이페이지/img/2.jpg" alt="photo6" /></li>
      </ul>
      <p class="controller">
        <span class="prev" onmouseover="slide_stop()" onmouseout="slide_start()"
          >&lang;</span
        >
        <span class="next" onmouseover="slide_stop()" onmouseout="slide_start()"
          >&rang;</span
        >
      </p>
      <div class="page">
        <span class="dot" onclick="currentSlide(0)"></span>
        <span class="dot" onclick="currentSlide(1)"></span>
        <span class="dot" onclick="currentSlide(2)"></span>
        <span class="dot" onclick="currentSlide(3)"></span>
        <span class="dot" onclick="currentSlide(4)"></span>
        <span class="dot" onclick="currentSlide(5)"></span>
      </div>
    </div>

 

 

 

- CSS

 

      @font-face {
        font-family: pretendard;
        src: url(../fontawesome-free-6.2.0-web/webfonts/Pretendard-Regular.woff)
          format("woff");
      }

      * {
        padding: 0;
        margin: 0;

        font-family: pretendard, sans-serif;
      }

      ul,
      li {
        list-style: none;
      }

      a {
        text-decoration: none;
      }

      body {
        text-align: center;

        margin-top: 50px;
      }

      #slideShow {
        position: relative;
        width: 1000px;
        height: 500px;

        margin: 70px auto;

        overflow: hidden;
      }

      .slides {
        position: absolute;
        left: 0;
        top: 0;

        transition: 0.5s ease-out;
      }

      .slides li {
        width: 1000px;
        height: 500px;
      }

      .slides img {
        width: 100%;
        height: 100%;

        object-fit: cover;
      }

      .slides li:not(:last-child) {
        float: left;
      }

      .controller span {
        position: absolute;
        top: 220px;

        border-radius: 50%;

        color: #fff;
        font-size: 30px;
        font-weight: bold;

        cursor: pointer;
      }

      .prev {
        left: 25px;
      }

      .prev:hover {
        transform: translateX(-10px);
      }

      .next {
        right: 30px;
      }

      .next:hover {
        transform: translateX(10px);
      }

      .page {
        position: absolute;
        width: 100%;
        bottom: 0;

        text-align: center;
      }

      .dot {
        cursor: pointer;

        display: inline-block;
        width: 15px;
        height: 15px;

        margin: 10px 2px;

        background-color: #bbb;
        border-radius: 50%;

        transition: background-color 0.6s ease;
      }

      .active,
      .dot:hover {
        background-color: #717171;
      }

 

 

- JavaScript

 

    <script>
    
      let slides = document.querySelector(".slides");
      let slideImg = document.querySelectorAll(".slides li");
      let dots = document.getElementsByClassName("dot");

      currentIndex = 0;
      slideCount = slideImg.length;

      prev = document.querySelector(".prev");
      next = document.querySelector(".next");

      slideWidth = 1000;

      console.log(currentIndex);

      dots[0].className += " active";

      function makeClone() {
        let cloneSlide_first = slideImg[0].cloneNode(true);
        // let cloneSlide_first = slideImg[5].cloneNode(true);
        let cloneSlide_last = slides.lastElementChild.cloneNode(true);

        slides.append(cloneSlide_first);
        slides.prepend(cloneSlide_last);
        //slides.insertBefore(cloneSlide_last, slides.firstElementChild);
      }
      makeClone();

      function initfunction() {
        slides.style.width = slideWidth * (slideCount + 2) + "px";
        slides.style.left = -slideWidth + "px";
      }
      initfunction();

      function showSlide(n) {
        for (let i = 0; i < slideCount; i++) {
          dots[i].className[i] = dots[i].className.replace(" active", "");
        }
        dots[n].className += " active";
        slides.style.left = -(n + 1) * slideWidth + "px";
        slides.style.trasition = "0.5s";
      }

      function currentSlide(n) {
        showSlide((currentIndex = n));
      }

      next.onclick = function () {
        if (currentIndex <= slideCount - 1) {
          slides.style.left = -(currentIndex + 2) * slideWidth + "px";
          slides.style.transition = "0.5s";
        }
        
        if (currentIndex === slideCount - 1) {
          setTimeout(function () {
            slides.style.left = -slideWidth + "px";
            slides.style.transition = "0s";
          }, 500);
          currentIndex = -1;
        }
        
        currentIndex += 1;
        for (let i = 0; i < slideCount; i++) {
          dots[i].className = dots[i].className.replace(" active", "");
        }
        
        dots[currentIndex].className += " active";
      };

      prev.onclick = function () {
        if (currentIndex >= 0) {
          slides.style.left = -currentIndex * slideWidth + "px";
          slides.style.transition = "0.5s";
        }

        if (currentIndex === 0) {
          setTimeout(function () {
            slides.style.left = -slideCount * slideWidth + "px";
            slides.style.transition = "0s";
          }, 500);
          currentIndex = slideCount;
        }

        currentIndex -= 1;
        for (let i = 0; i < slideCount; i++) {
          dots[i].className = dots[i].className.replace(" active", "");
        }

        dots[currentIndex].className += " active";
      };

      let interval = setInterval(function () {
        next.onclick();
      }, 2000);
      
      function slide_stop() {
        clearInterval(interval);
      }
      
      function slide_start() {
        interval = setInterval(function () {
          next.onclick();
        }, 2000);
      }
      
    </script>

 

 

0
가만히 두었을 때

마우스로 클릭하지 않아도 자동으로 슬라이드가 넘어간다. 

 

 

0
마우스로 클릭했을 때

 

그리고 이전 / 다음 버튼에 onmouseover와 onmouseout 속성을 사용해서 마우스를 올렸을 때 슬라이드가

멈추고, 마우스를 뗐을 때 슬라이드가 다시 시작되도록 했다.

 

 

 

<주석 달며 공부한 것>

 

 

    <script>
      let slides = document.querySelector(".slides"); //slides(ul)
      let slideImg = document.querySelectorAll(".slides li"); //slides(ul)>li
      let dots = document.getElementsByClassName("dot"); //page>.dot
      currentIdx = 0;
      slideCount = slideImg.length; // li개수 6
      prev = document.querySelector(".prev"); // 좌측 버튼
      next = document.querySelector(".next"); // 우측 버튼
      slideWidth = 1000; //이미지 가로 크기
      dots[0].className += " active"; // active는 활성화 된 버튼의 색상, 지금은 0번 버튼

      function makeClone() {
        let cloneSlide_first = slideImg[0].cloneNode(true); // li 첫 번째를 복사
        let cloneSlide_last = slides.lastElementChild.cloneNode(true); // ul의 마지막 자식 복사
        slides.append(cloneSlide_first); //ul의 마지막에 첫번째li를 복사
        slides.insertBefore(cloneSlide_last, slides.firstElementChild); //ul의
      }
      makeClone(); // 초기 세팅으로 기존 6개의 li에서 8개의 li로 세팅

      function initfunction() {
        slides.style.width = slideWidth * (slideCount + 2) + "px"; //ul width 8000px
        slides.style.left = -slideWidth + "px";
        //1000px 앞으로, 첫 번째가아닌 두번째에서 시작, 여기서 두번째가 실제 첫 번째 li 이미지임
      }
      initfunction(); // 두번째에서 시작하는 이유는 복사한 마지막 li가 현재 첫 번째에 있어서, 기존 첫번째 이미지가 두 번째 칸에있기 때문

      function showSlide(n) {
        for (let i = 0; i < slideCount; i++) {
          // li개수만큼 반복, 모든 li에 적용하고자
          dots[i].className = dots[i].className.replace(" active", "");
          // 모든 dots를 확인하며 클래스에 active가 있으면 해당 클래스를 없앰
        }
        dots[n].className += " active"; //활성화될 순서의 dot에만 active를 추가함
        slides.style.left = -(n + 1) * slideWidth + "px";
        // ul의 left에 값을 변경함, -(n+1) 이 부분은 이미지의 순서를 의미하고, 순서만큼에 이미지 가로값인 slideWidth를 곱하고, 그 값만큼 left 이동, 즉 왼쪽으로 이미지가 이동되며 순서를 정의함
        slides.style.trasition = "0.5s"; // ul이 이동하는 모션을 추가
      }

      function currentSlide(n) {
        // n은 이미지 순서를 의미
        showSlide((currentIdx = n));
        // 매개변수 n만큼(순서) showSlide함수에 적용하는데, currentIdx에 사용하는 이유는 다른 곳에서도 currentIdx(순서)를 사용하기 위함
      }

      next.onclick = function () {
        // 우측버튼을 클릭하면.
        if (currentIdx <= slideCount - 1) {
          // 현재 순서가 li의 개수 -1보다 작거나 같나? 즉, 현재 순서가 마지막이 아니면 동작

          slides.style.left = -(currentIdx + 2) * slideWidth + "px";
          // 5 0 1 2 3 4 5 0  [initfunction에서 이런식으로 li를 만들었음]
          // 처음 5를 비추는 left값이 -1000
          // 0은 -2000, 1은 -3000 ...

          // 순서만큼의 left값을 적용해서 이전 이미지는 왼쪽으로 밀리며, 현재 순서가 화면에 보임
          slides.style.transition = "0.5s"; //ul이 이동하는 모션을 추가
        }
        if (currentIdx === slideCount - 1) {
          // 현재 순서가 마지막 순서냐?
          setTimeout(function () {
            slides.style.left = -slideWidth + "px";
            // 첫번재 순서로 이동(마지막 이미지가 첫번째에 있기때문에 left에 -1000만큼 이동해서 기존 첫번째 이미지인 두번째 순서를 보여줌
            slides.style.transition = "0s";
            // 자연스러운 이미지 표현을 위해 해당 부분은 트렌지션 없이 이동
          }, 500);

          currentIdx = -1;
          // 마지막 순서에 도달했기 때문에 처음 순서로 초기화,
          // 해당 조건이 끝난 후 아래 코드에 곧바로 currentIdx를 1 더하기 때문에 -1를 적용함
          // 결국 0으로 만들기 위함이기 때문에
        }
        currentIdx += 1; //클릭마다 순서 +1
        for (let i = 0; i < slideCount; i++) {
          dots[i].className = dots[i].className.replace(" active", "");
          // dot에 active 클래스를 없앰
        }
        dots[currentIdx].className += " active";
        // 현재 순서인 dot에 active 클래스를 추가
      };

      prev.onclick = function () {
        // next와 동일하지만 순서의 방향만 반대임
        if (currentIdx >= 0) {
          slides.style.left = -currentIdx * slideWidth + "px";
          slides.style.transition = "0.5s";
        }
        if (currentIdx === 0) {
          setTimeout(function () {
            slides.style.left = -slideCount * slideWidth + "px";
            slides.style.transition = "0s";
          }, 500);
          currentIdx = slideCount;
        }
        currentIdx -= 1;
        for (let i = 0; i < slideCount; i++) {
          dots[i].className = dots[i].className.replace(" active", "");
        }
        dots[currentIdx].className += " active";
      };
    </script>

 

 

    <script>
      let slides = document.querySelector(".slides");
      let slideImg = document.querySelectorAll(".slides li");
      let dots = document.getElementsByClassName("dot");
      currentIdx = 0; slideCount = slideImg.length; dots[0].className += " active";
      prev = document.querySelector(".prev"); //이전 버튼
      next = document.querySelector(".next"); //다음 버튼
      slideWidth = 1000; //슬라이드이미지 넓이

      makeClone(); // 처음이미지와 마지막 이미지 복사 함수
      initfunction(); //슬라이드 넓이와 위치값 초기화 함수

      function makeClone() {
        let cloneSlide_first = slideImg[0].cloneNode(true);
        let cloneSlide_last = slides.lastElementChild.cloneNode(true);
        slides.append(cloneSlide_first);
        slides.insertBefore(cloneSlide_last, slides.firstElementChild);
      }

      function initfunction() {
        slides.style.width = slideWidth * (slideCount + 2) + "px";
        slides.style.left = -slideWidth + "px";
      }

      function currentSlide(n) {
        showSlide((currentIdx = n));
        console.log(currentIdx);
      }

      function showSlide(n) {
        for (i = 0; i < slideImg.length; i++) {
            dots[i].className = dots[i].className.replace(" active", "");
        }

        dots[n].className += " active"; slides.style.left = -(n + 1) * slideWidth + "px"; slides.style.transition = "0.5s";
      }

      function currentSlide(n) {
        showSlide((currentIdx = n));
      }

      next.onclick = function () {
        if (currentIdx <= slideCount – 1) { //슬라이드이동
            slides.style.left = -(currentIdx + 2) * slideWidth + "px"; slides.style.transition = "0.5s";
        }

        if (currentIdx === slideCount - 1) { //마지막 슬라이드 일때
            setTimeout(function () {
                //0.5초동안 복사한 첫번째 이미지에서, 진짜 첫번째 위치로 이동
                slides.style.left = -slideWidth + "px";
                slides.style.transition = "0s";
            }, 500);
            currentIdx = -1;
        }

        currentIdx += 1; for (i = 0; i < slideImg.length; i++) {
            dots[i].className = dots[i].className.replace(" active", "");
        }

        dots[currentIdx].className += " active";
      };

      prev.onclick = function () {//이전 버튼 눌렀을때
        console.log(currentIdx);

        if (currentIdx >= 0) {
            slides.style.left = -currentIdx * slideWidth + "px"; slides.style.transition = "0.5s";
        }

        if (currentIdx === 0) {
            setTimeout(function () { slides.style.left = -slideCount * slideWidth + "px"; slides.style.transition = "0s"; }, 500); currentIdx = slideCount;
        }

        currentIdx -= 1; for (i = 0; i < slideImg.length; i++){
            dots[i].className = dots[i].className.replace(" active", "");
        }
        dots[currentIdx].className += " active";
      };

      var interval = setInterval(function () {
            next.onclick();
      }, 2000);

      function slide_stop() {
        clearInterval(interval);
      }

      function slide_start() {
        interval = setInterval(function () { next.onclick(); }, 2000);
      }
    </script>

 

 

 

 

 

 

 

 

 

 

 

* 이미지 출처 

instagram : @postershop.kr

 

 

반응형