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