[JS] Airbnb 클론코딩 with HTML/CSS - day4

jiseong·2021년 9월 9일
0

T I Learned

목록 보기
60/291
post-custom-banner

이미지 슬라이드

이미지 슬라이드의 원리라면 컨테이너 요소에 사용할 이미지 width를 지정해놓고 row 요소에서 flex를 사용하여 하위 요소들을 가로로 나열 시킨 후 width를 이미지 갯수만큼 퍼센트를 지정해주면 아래와 같이 나열된다.

그 후, width가 지정된 컨테이너에 overflow: hidden을 선언해주면 하나의 이미지만 보이게 된다.
여기서 이미지를 옮길 때는 자바스크립트를 이용하여 row요소의 margin-left 값을 조정해주면 슬라이드를 구현할 수 있다.

.img-slider-container {
    width: 300px;
    height: 200px;
    border-radius: 15px;
    overflow: hidden;
}
.img-slider-container .img-slider-row {
    display: flex;
    width: 300%; /* 이미지 갯수에 따라 지정 */
    height: 100%;
    margin-left: 0%;
    transition: margin 0.5s;
}
.img-slider-container .img-slider-col {
    width: 100%;
    height: 100%;
}
.img-slider-col img {
    object-fit: cover;
    width: 100%;
    height: 100%;
}
// for img slider
const sliderContainers = document.querySelectorAll('.img-slider-container');

class Slider {
  constructor(target){
    this.sliderContainer = target;
    this.dots = [...this.sliderContainer.querySelectorAll(".dot")];
    this.sliderRow = target.querySelector('.img-slider-row');
    this.imgLength = target.querySelectorAll('.img-slider-col').length * 100 - 100;
    this.sliderRow.style.width = `${this.imgLength + 100}%`;
    this.curPosition = 0;

    this.onEvent();
  }

  moveSlider(e) {
    const isMinMaxSlider = () => this.curPosition > this.imgLength || this.curPosition < 0;

    if(e.target.className.includes('prev')){
      this.curPosition-= 100;

      this.toggleBtn();

      if(isMinMaxSlider()) this.curPosition = 0;

      this.toggleDot(this.curPosition);
      this.sliderRow.style.marginLeft = `-${this.curPosition}%`;

    } else if(e.target.className.includes('next')){
      this.curPosition+= 100;

      this.toggleBtn();

      if(isMinMaxSlider()) this.curPosition = this.imgLength;

      this.toggleDot(this.curPosition);
      this.sliderRow.style.marginLeft = `-${this.curPosition}%`;
    }
  }

  onEvent(){
    // 요소가 아닌 해당 class 인스턴스 바인딩
    this.sliderContainer.addEventListener('click', this.moveSlider.bind(this));
  }

  toggleBtn() {
    const prev = this.sliderContainer.querySelector('.prev');
    const next = this.sliderContainer.querySelector('.next');

    const isMax = () => this.curPosition === this.imgLength;

    if(this.curPosition === 0){
      prev.style.visibility = 'hidden';
      next.style.visibility = 'visible';
    } else if (isMax()){
      prev.style.visibility = 'visible';
      next.style.visibility = 'hidden';
    } else {
      prev.style.visibility = 'visible';
      next.style.visibility = 'visible';
    }
  }

  toggleDot(value) {
    this.dots.map( (dot, idx) => {
      if(idx === (value / 100)) return dot.classList.add("active");

      dot.classList.remove("active");
    });
  };
}

[...sliderContainers].map(sliderContainer => new Slider(sliderContainer));

버블링을 활용한 버튼요소 핸들링

function moveSlider(e){
  console.log(e.target);
}
    
sliderContainer.addEventListener('click', moveSlider);

각 버튼에 일일이 이벤트리스너를 해주지 않아도 버블링을 이용하여 이전, 다음 버튼등에 대한 이벤트 핸들링을 할 수 있다.

슬라이드는 이전에 만들어본 경험이 있어서 크게 막히는 부분은 없었다. 아직 인터랙션에서 부족한 부분이 많지만 이번 클론코딩은 HTML, CSS 위주로 하기때문에 다음 화면을 만들어 볼 예정이다.

post-custom-banner

0개의 댓글