[Javascript] 슬라이더 만들기

방예서·2022년 4월 28일
0

JavaScript

목록 보기
3/6
post-custom-banner

220427

  window.onload = function() {
    const kindWrap = document.querySelector('.kind_wrap');
    const slider = kindWrap.querySelector('.slider');
    const sliderLis = slider.querySelectorAll('li');
    const moveBtn = kindWrap.querySelector('.arrow');

    const liWidth = sliderLis[0].clientWidth;
    
    //ul 넓이 계산해주기
    //이 값을 css로 전달해주어야함
    //.kind_wrap > .kind_slider 여기로
    const sliderWidth = liWidth * sliderLis.length;
    slider.style.width = `${sliderWidth}px`; //sliderWidth + 'px' 와 같습니다.

    //click listner 만들기
    moveBtn.addEventListener('click', moveSlide);

    function moveSlide(event) {
      event.preventDefault();
      let clicktext = event.target.textContent;
    }
  };
  

window.onload
window.addEvenetListener('load', 할일함수)

와 같다.


  window.onload = function() {
    const kindWrap = document.querySelector('.kind_wrap');
    const slider = kindWrap.querySelector('.slider');
    const sliderLis = slider.querySelectorAll('li');
    const moveBtn = kindWrap.querySelector('.arrow');
    let moveDist = 0;
    let currentNum = 0;

    const liWidth = sliderLis[0].clientWidth;
    
    //ul 넓이 계산해주기
    //이 값을 css로 전달해주어야함
    //.kind_wrap > .kind_slider 여기로
    const sliderWidth = liWidth * sliderLis.length;
    slider.style.width = `${sliderWidth}px`; //sliderWidth + 'px' 와 같습니다.

    //click listner 만들기
    moveBtn.addEventListener('click', moveSlide);

    function moveSlide(event) {
      event.preventDefault();
      console.log(event.target.className);
      let clickclass = event.target.className; //class 이름(prev, next)

      //이전
      if (clickclass === 'prev') {
        moveDist += liWidth;
        slider.style.left = `${moveDist}px`;
        currentNum -= 1;
      } else { //다음
        moveDist += -liWidth;
        slider.style.left = `${moveDist}px`;
        currentNum +=1;
      }
      console.log(moveDist, currentNum);
    }

  };

moveDist, currentNum 은 onload가 끝나도 살아있다. 왜일까?
moveBtn에 참조 되어 있기 때문에 사라지지 않고 살아있다.

만약에 중간에 moveDist, currentNum을 사용하는 함수가 있다고 해서 이때도 사라지지 않을까?
함수가 끝나는 시점에 외부 참조가 없어서 가비지컬렉션에 의해 수거대상이 된다.


버튼으로 넘어가게 동작하고,

무한 루프까지 했다.

      //이전
      if (clickclass === 'prev') {
        if (currentNum === 0) { //첫번째니?
          moveDist = -(sliderWidth-liWidth);
          slider.style.left = `${moveDist}px`;
          currentNum = sliderLis.length-1;
        } else {
          moveDist += liWidth;
          slider.style.left = `${moveDist}px`;
          currentNum--;
        }
      } 
      
      //다음
      else { 
        if (currentNum === (sliderLis.length-1)) { //마지막이니?
          moveDist = 0;
          slider.style.left = `${moveDist}px`;
          currentNum = 0;
        } else {
          moveDist += -liWidth;
          slider.style.left = `${moveDist}px`;
          currentNum++;
        }
      }

애니메이션을 주기 위해

.kind_wrap > .kind_slider .slider {
      position: relative;
      transition: all 500ms ease;
    }

css파일에 이렇게 넣었다.

이 때 문제는 첫 번째로 넘길 때 애니메이션이 안 먹는다.
이유는 맨 처음 값은 left: auto 이기 때문
그래서 script로

slider.style.left = 0;

을 주면 잘 작동한다.

근데 이걸 옵션 값을 다른 사람이 쉽게 바꿀 수 있게 하기 위해서 옵션 부분을 script에 주기로 한다.

slider.style.transition = 'all 500ms ease';

근데 이렇게 하니까 무한 루프 될 때(1에서 4가고 4에서 1 갈때) 그 과정이 다 보인다.
일단 무한 루프 안되게 코드를 수정한다.


지금 코드가 중복되어 불-편하다.

함수로 묶는다.

      //이전
      if (clickclass === 'prev') {
        if (currentNum === 0) return;
        move(1);
      } 
      
      //다음
      else { 
        if (currentNum === (sliderLis.length-1)) return;
        move(-1);
      }

이제 아까 미뤄놨던 애니메이션 해보겠다.

아이디어는

  1. 슬라이더 양 옆에 클론 생성한다.
  2. 버튼을 누르면 일단 넘어가기.
  3. 첫번째/마지막 슬라이드니?
    • 아니다. 그러면 다시 2번으로.
    • 맞다. 그러면 기다려.
      애니메이션 끝날 때까지 기다렸다가 클론말고 진짜 해당 부분으로 옮기기
      이 때 애니메이션을 꺼야지 움직이는 모션이 보이지 않는다.

그래서 첫번째 노드, 마지막 노드를 복제한다.

    const cloneF = sliderLis[0].cloneNode(true); //First의 clone
    const cloneL = sliderLis[sliderLis.length-1].cloneNode(true); //Last의 clone

...

	slider.style.width = `${sliderWidth}px`;

그냥 클론만 하면 안나오니까 밑에 slider width 값도 주자.

    slider.insertBefore(cloneL, sliderLis[0]);
    slider.appendChild(cloneF);

마지막 클론은 slider 맨 앞에 끼워넣기(insertBefore)
첫번째 클론은 slider에 추가하면 알아서 맨 뒤로 간다.

근데 이렇게 하니까 또 slideLis가 문제가 생김.
복제하기 전에 slideLis를 계산하니까 클론이 없기 전의 길이로 저장되어 있다.
그래서 밑에 부분에 querySelector를 다시 해서 클론 포함한 길이를 계산하도록 하자.

잊지말고 바꾼 값들을 잘 초기화 해주기로 한다.

	//다음 버튼 눌렀을 때
		//일단 움직여
        move(-1);
		//마지막이니
        if (currentNum === (sliderCloneLis.length-1)) { 
          //애니메이션 끝날 때까지 기다렸다가 실행하는 함수
          setTimeout(() => {
            //애니메이션 잠시 꺼
            slider.style.transition = 'none';
            
            //진짜 첫번째/마지막 슬라이드로 가기
            moveDist = -liWidth;
            slider.style.left = `${-liWidth}px`;
            
            //진짜 첫번째/마지막 currentNum으로 할당
            currentNum = 1;
          }, speedTime)
        }

이때 애니메이션을 끄기 위해 none 값을 준다.
이렇게 껐기 때문에 움직일 때마다 애니메이션은 실행될 수 있게 move() 함수로 transition을 주기로 한다.

이런 식으로 이전 버튼에도 잘 추가하면 동작한다.

profile
console.log('bang log');
post-custom-banner

0개의 댓글