이미지들이 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]