📃

swiper + observerクラス

2023/01/13に公開約5,200字

swiper + observerクラスの試作テンプレートです
observerを用いて、画面外にいる時はautoplayを止めます

index.js

index.js
const swiperTarget01 = ".js-io-swiper";
new SwiperIO(swiperTarget01,
  { //option except delay and disableOnInteraction
    pagination: { //if type: 'bullets', this is not required
      el: `${swiperTarget01}-pagination`,
      type: 'progressbar',
    },
  },
  { //params.autoplay: delay and disableOnInteraction
    delay: 1500,
    disableOnInteraction: true
  }
);

const swiperTarget02 = ".js-io-swiper02";
new SwiperIO(swiperTarget02,
  { //option except delay and disableOnInteraction
    // pagination: { //if type: 'bullets', this is not required
      // el: `${swiperTarget02}-pagination`,
      // type: 'progressbar',
   // },
  },
  { //params.autoplay: delay and disableOnInteraction
    // delay: 3000,
    disableOnInteraction: true
  }
);

_SwiperIO.js

_SwiperIO.js
import Swiper from 'swiper/bundle';
import 'swiper/css/bundle';
const { log } = console;

export class SwiperIO {
  constructor(target, option, autoPlayOption, autoHeight = true) {
    //get target DOM
    this.target = target;
    this.DOM = {};
    this.DOM.target = document.querySelector(target);
    if (!this.DOM.target) return;

    //target class except "."
    this.targetClass = target.split(".")[1];

    //aadd JS class to DOM elements that have "swiper-****" class, e.g. "swiper-pagination"
    this.DOM.dataElements;
    this._addClassToDataElements();

    //option
    this.option = option;

    //Swiper.params.autoplay: delay and disableOnInteraction
    this.autoPlayOptionDelay = autoPlayOption.delay ? autoPlayOption.delay : 3000;
    this.autoPlayOptionDisableOnInteraction = autoPlayOption.disableOnInteraction ? autoPlayOption.disableOnInteraction : false;

    //fix height
    this.autoHeight = autoHeight;
    this._height();

    this.swiper = this._initSwiper();
    this._observer();
  }

  _addClassToDataElements() {
    this.DOM.dataElements = document.querySelectorAll(`*[data-swiper-name=${this.targetClass}]`);

    this.DOM.dataElements.forEach(el => {
      if (el.classList.contains("swiper-pagination")) el.classList.add(`${this.targetClass}-pagination`);
      if (el.classList.contains("swiper-scrollbar")) el.classList.add(`${this.targetClass}-scrollbar`);
      if (el.classList.contains("swiper-button-next")) el.classList.add(`${this.targetClass}-next`);
      if (el.classList.contains("swiper-button-prev")) el.classList.add(`${this.targetClass}-prev`);
    });
  }

  _height() {
    if (this.autoHeight) {
      //height調整
      this.DOM.target.querySelector(".swiper-wrapper").setAttribute("style", "height: auto");
    }
  }

  _initSwiper() {
    const option = {
      loop: true,
      pagination: {
        el: `${this.target}-pagination`,
        type: 'bullets', //default
        clickable: true,
      },
      navigation: {
        nextEl: `${this.target}-next`,
        prevEl: `${this.target}-prev`,
      },
      scrollbar: {
        el: `${this.target}-scrollbar`,
      },
    }
    Object.assign(option, this.option)

    //initialize swiper
    return new Swiper(this.target, option);
  }

  _observer() {
    //画面に入った時だけ処理する
    const observer = new IntersectionObserver(entries => {
      entries.forEach(entry => {
        entry.isIntersecting ? this._start() : this._stop();
      });
    });

    //observer監視開始
    observer.observe(this.DOM.target);
  }

  _start(options) {
    options = {
      delay: this.autoPlayOptionDelay,
      disableOnInteraction: this.autoPlayOptionDisableOnInteraction,
    }
    this.swiper.params.autoplay = options;
    this.swiper.autoplay.start();
  }

  _stop() {
    this.swiper.autoplay.stop();
  }
}

html

htmlではdata-swiper-nameとswiperのクラスを一致させれば勝手にjsクラスを付与します
なので、新しく作る際の書き換えはdata-swiper-nameとswiperのクラスを一括置換するだけで終わります

index.html
<p>クラス化+IO組み込みしたswiper↓</p>
<div class="swiper js-io-swiper">
  <div class="swiper-wrapper">
    <div class="swiper-slide"><img src="https://picsum.photos/id/45/1200/840" alt="Swiper01"></div>
    <div class="swiper-slide"><img src="https://picsum.photos/id/55/1200/840" alt="Swiper02"></div>
    <div class="swiper-slide"><img src="https://picsum.photos/id/96/1200/840" alt="Swiper03"></div>
  </div>
  <div class="swiper-pagination" data-swiper-name="js-io-swiper"></div>
  <div class="swiper-scrollbar" data-swiper-name="js-io-swiper"></div>
  <div class="swiper-button-prev" data-swiper-name="js-io-swiper"></div>
  <div class="swiper-button-next" data-swiper-name="js-io-swiper"></div>
</div>


<p>クラス化+IO組み込みしたswiper02↓</p>
<div class="swiper js-io-swiper02">
  <div class="swiper-wrapper">
    <div class="swiper-slide"><img src="https://picsum.photos/id/45/1200/840" alt="Swiper01"></div>
    <div class="swiper-slide"><img src="https://picsum.photos/id/55/1200/840" alt="Swiper02"></div>
    <div class="swiper-slide"><img src="https://picsum.photos/id/96/1200/840" alt="Swiper03"></div>
    </div>
  <div class="swiper-pagination" data-swiper-name="js-io-swiper02"></div>
  <div class="swiper-scrollbar" data-swiper-name="js-io-swiper02"></div>
  <div class="swiper-button-prev" data-swiper-name="js-io-swiper02"></div>
  <div class="swiper-button-next" data-swiper-name="js-io-swiper02"></div>
</div>

Discussion

ログインするとコメントできます