이미지 슬라이더

js·2022년 5월 11일
0

원리

  • 이미지들이 li 요소에 담겨있고 li 요소들에 float: left를 주어서 수평방향으로 여러장의 이미지들이 배치 되어 있는 형태이다.

  • ul 요소는 width값이 정해져 있고overflow: hidden이 적용되어 있어서서 한번에 하나의 이미지만 보여진다.

  • 이미지 전환은 .next 버튼을 누를 때마다 ul 요소를 left: -1000px, 왼쪽으로 1000px(하나의 이미지 width값)만큼 이동시키면 다음 이미지 요소가 나타나는 방식으로 구현한다.

  • autoPlay 기능은 setInterval('다음 이미지로 가기()', 3000)와 같이 setInterval을 줘서 구현한다.

  • 인디케이터(조그만 동그라미)는 잦은 변경이 필요하므로 setIndicator()라는 현재 인디케이터를 새로 렌더링하는 함수가 따로 존재한다.

코드

  onClickIndicator(event) {
    const indexPosition = parseInt(event.target.dataset.index, 10);
    /* 인디케이터 사이 빈공간을 클릭하면 indexPosition이 undefined가 뜨는 경우가 있어서 이를 방지 하기 위한 if문이다 */
    if (Number.isInteger(indexPosition)) {
      this.#currentPostion = indexPosition;
      this.sliderListEl.style.left = `-${
        this.#slideWidth * this.#currentPostion
      }px`;
      this.setIndicator();
    }
  }

  moveToRight() {
    this.#currentPostion += 1;
    // index 6에서 7로 가는 경우 0으로 보내준다
    if (this.#currentPostion === this.#slideNumber) {
      this.#currentPostion = 0;
    }
    this.sliderListEl.style.left = `-${
      this.#slideWidth * this.#currentPostion
    }px`;
    if (this.#autoPlay) {
      clearInterval(this.#intervalId);
      this.#intervalId = setInterval(this.moveToRight.bind(this), 3000);
    }
    this.setIndicator();
  }

  moveToLeft() {
    this.#currentPostion -= 1;
    // index 0에서 -1로 가는 경우 6으로 보내준다
    if (this.#currentPostion === -1) {
      this.#currentPostion = this.#slideNumber - 1;
    }
    this.sliderListEl.style.left = `-${
      this.#slideWidth * this.#currentPostion
    }px`;
    // autoPlay가 활성화 된 경우에만 기존 interval을 clear 하고 재시작 한다.
    // interval을 안 비울경우 next버튼을 눌렀을 때 3초가 새로 시작되지 않기 때문이다. 
    if (this.#autoPlay) {
      clearInterval(this.#intervalId);
      this.#intervalId = setInterval(this.moveToRight.bind(this), 3000);
    }
    this.setIndicator();
  }

  createIndicator() {
    const docFragment = document.createDocumentFragment();
    for (let i = 0; i < this.#slideNumber; i += 1) {
      const li = document.createElement('li');
      li.dataset.index = i;
	  //새로 생성할 요소들은 DocumentFragment에 담아주자 
      docFragment.appendChild(li);
    }
    this.indicatorWrapEl.querySelector('ul').appendChild(docFragment);
  }

  setIndicator() {
    // 현재 active 되어있는 인디케이터 클래스는 제거하고 현재 포지션에 해당되는 인디케이터에 active 클래스 추가
    this.indicatorWrapEl.querySelector('li.active')?.classList.remove('active');
    this.indicatorWrapEl
      .querySelector(`ul li:nth-child(${this.#currentPostion + 1})`)
      .classList.add('active');
  }
}

기타

  • Dom조작 최적화에는 createDocumentFragment()를 사용하자.

    DocumentFragment는 기본적으로 DOM과 동일하게 동작하지만, HTML의 DOM 트 리에는 영향을 주지 않으며, 메모리에서만 정의됩니다. 불필요한 reflow, repaint를 방지 할 수 있습니다.

출처: https://7942yongdae.tistory.com/70 [프로그래머 YD]

0개의 댓글