vue-awesome-swiper Loop + Autoplay + Pagination 적용하기

남양주개발자

·

2020. 12. 1. 08:00

728x90
반응형

Nuxt.js에서 vue-awesome-swiper loop pagination 버그 해결하는 방법

Swiper 라이브러리에서 무한루프(loop), 페이지네이션(pagination), 자동재생(autoplay)를 유기적으로 버그없이 잘 동작하게 구현하는 것은 생각보다 까다로울 수 있습니다. 이번 포스팅에서는 Swiper 라이브러리를 활용해서 3가지 기능의 타이밍을 정확하게 제어하여 Carousel Slider 기능을 구현해보도록 하겠습니다.

라이브러리 버전

  • vue-awesome-swiper@4.1.1
  • swiper@5.4.5

구현할 최종 결과물

우리가 구현할 최종 결과물은 아래와 같습니다. 

우리가 구현할 최종 결과물

코드

vue-awesome-swiper를 활용해서 구현한 예시는 아래 코드와 같습니다.

// template code
<template>
  <div class="banner-view">
    <div class="container">
      <div v-once v-swiper:swiper="swiperOption" class="swiper-container">
        <ul class="swiper-wrapper">
          <li
            v-for="n in 3"
            :key="`banner-swiper-slide--${n}`"
            class="swiper-slide"
          >
            {{ n }}
          </li>
        </ul>
        <div class="swiper-pagination"></div>
      </div>
    </div>
    <div class="swiper-progress" :class="{ start: startProgress }">
      <div class="bar"></div>
    </div>
  </div>
</template>

v-swiper를 적용하는 태그에 v-once 디렉티브를 같이 적용해야 됩니다. v-once 디렉티브를 넣는 이유가 궁금하다면 아래 포스팅을 확인해주세요.

 

무한루프(loop)와 페이지네이션(pagination) 그리고 자동재생 기능을 적용하기 위해 swiper 옵션에 loop 프로퍼티를 true 그리고 pagination을 활성화 시킵니다. loop, pagination, autoplay가 유기적으로 잘 실행되려면 타이밍을 잘 제어해야되는데요. swiper 이벤트 4가지로 해당 타이밍을 적당히 컨트롤하면 됩니다. 타이밍을 제어하기 위해 사용되는 이벤트는 총 4가지 (init, sliderMove, slideChangeTransitionStart, transitionEnd)입니다.

init 이벤트는 swiper가 초기화될 때 실행됩니다. init 이벤트가 트리거될 때 우리는 progressbar를 활성화시키는 startProgress 변수를 true로 변경합니다. startProgress 변수가 true로 변경되면 하단의 progressbar가 동작하기 시작합니다.

sliderMove 이벤트는 사용자가 임의로 swiper의 슬라이드를 움직였을 때 트리거되는 이벤트입니다. 사용자가 임의로 슬라이드를 움직일 경우 자동재생 기능을 stop 시킨 후 startProgress 변수를 false로 변경합니다.

slideChangeTransitionStart 이벤트는 사용자가 슬라이드를 움직였고, 실제 다른 슬라이드로 전환을 시작할 때 트리거되는 이벤트입니다. 실제 다른 슬라이드로 전환될 시점은 슬라이드가 이동할 때까지 자동재생이 실행되면 안되는 경우입니다. 슬라이드가 이동을 시작할 타이밍에 자동재생을 중지시킵니다.

마지막으로 transitionEnd 이벤트는 swiper에서 어떠한 이동 동작이 마무리되는 시점에 트리거되는 이벤트입니다. 동작이 마무리되면 슬라이드가 최종적으로 이동을 완료된 시점이기 때문에 해당 이벤트가 트리거되면 자동재생을 다시 시작해줍니다.

 

<script>
export default {
  data() {
    return {
      startProgress: false,
      swiperOption: {
        loop: true,
        threshold: 20,
        autoplay: {
          delay: 5000
        },
        on: {
          init: this.init,
          sliderMove: this.stopAutoplay,
          slideChangeTransitionStart: this.stopAutoplay,
          transitionEnd: this.startAutoplay
        },
        pagination: {
          el: '.swiper-pagination',
          clickable: true
        }
      }
    }
  },
  methods: {
    init() {
      this.startProgress = true
    },
    stopAutoplay() {
      try {
        this.swiper.autoplay.stop()
        this.startProgress = false
      } catch (err) {
        console.error(err)
      }
    },
    startAutoplay() {
      try {
        this.swiper.autoplay.start()
        this.startProgress = true
      } catch (err) {
        console.error(err)
      }
    }
  }
}
</script>

swiper progressbar는 CSS animation으로 구현합니다.

<style lang="scss" scoped>
// progress animation 적용
@keyframes progress {
  from {
    transform: translateX(-100%);
  }

  to {
    transform: translateX(0);
  }
}
.banner-view {
  // change white bullet
  .swiper-pagination {
    bottom: 5px;
    left: 50%;
    transform: translateX(-50%);
    .swiper-pagination-bullet {
      background: rgba(255, 255, 255, 0.5);
      margin-right: 8px;
      &.swiper-pagination-bullet-active {
        background: #fff;
      }
    }
  }
  
  .swiper-progress {
    position: absolute;
    bottom: 0;
    width: 100%;
    z-index: 1;
    background-color: #f1f3f5;
    .bar {
      width: 100%;
      height: 4px;
      transform: translateX(-100%);
      background-color: #7950f2;
    }
    &.start {
      .bar {
        animation-duration: 5s;
        animation-iteration-count: infinite;
        animation-name: progress;
      }
    }
  }
}
</style>

 

728x90
반응형
그리드형

이 포스팅은 쿠팡파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

💖 저자에게 암호화폐로 후원하기 💖

아이콘을 클릭하면 지갑 주소가자동으로 복사됩니다