TEORICO

【JavaScript】Swiper ページネーション2種類使いたいけど…

【JavaScript】Swiper ページネーション2種類使いたいけど…

Swiperのページネーションで2種類使いたいんだけど…

jQuery依存も無く、軽量・オプション・イベント・メソッドが豊富で使用しやすいことで有名なスライダー「Swiper 」

個人的にここ最近スライダーの実装がある場合は「Swiper」1択です。

今回はそのSwiperの中でも、ページネーションについての話です。

サンプルソースはページ下部にありますので、速くソース見たい!っていう方は最下部へ。

※今回記述するのは2020/10/08時点でのVer.6.3.2です。他バージョンでの動作は保証できませんのでご了承ください。(Ver.5系で動作するのは一応確認しています)

※ 2023/06/26  v7 以降の場合の注意点を追記しました。基本的には Swiper の公式の書き方に合わせてもらえればOKです。
v.6以前と、v.7  以降は、

  • ・class名 から swiper-container が削除
  • ・swiper-container が実行用のセレクタだったのが、swiper だけで良くなった

上記の変更点が重要な部分だと思います。

ページネーションの種類

Swiperのページネーションには様々な種類があります。

  • bullet → いわゆるまるぽち
  • fraction → ページ数の5枚あったとしたら 1/5 みたいに最大枚数と、現在の枚数の数字を出す
  • progressbar → プログレスバー 進捗具合です。身近なのはダウンロードの時とかよく画面に出るようなゲージです。
  • custom → 表示方法などを上記のいずれでもない場合や、好きに変更したい場合はこちらを付与する

この4種類です。

詳細はSwiperのデモにありますので、そちらをご覧ください。

Swiper 公式デモ

 

種類は豊富にあるので、大体はこのうちのどれかで事足りるのですが…

2種類同時に使用したいという要望があることがあります。

1つのSwiper に対して同時に使用させるのは多分無理なので…

やり方として考えられるのは下記の3種類かな?と思います。

  • サムネイル用のSwiperを作成し、それを bullet のページネーションとして連動させる方法
  • SwiperにはScrollbarというオプションがあるので、それをページネーション風にCSSを記述
  • 自作する

今回紹介するのは最後の自作する方法です。

ページネーションは bullet を使用して、fraction側を自作します。

Swiperの準備

HTMLの準備

Swiperで必要なHTMLを準備します。

*Swiper v.7 より 記述方法が違いますので注意してください。

Swiper v.6 まで

<div class="swiper">
  <div class="swiper-container">
    <div class="swiper-wrapper">
      <div class="swiper-slide"><img src="https://placehold.jp/150x150.png" alt=""></div>
      <div class="swiper-slide"><img src="https://placehold.jp/150x150.png" alt=""></div>
      <div class="swiper-slide"><img src="https://placehold.jp/150x150.png" alt=""></div>
    </div>
    <div class="swiper-custom-fraction js-custom-fraction">
      <span class="js-currentNum">1</span>/<span class="js-Maxnum"></span> 
      </div>
  </div>
  <div class="swiper-pagination"></div>
</div>

Swiper v.7 以降

<div class="xxx"> <!-- 任意の class名 -->
  <div class="swiper">
      <div class="swiper-wrapper">
        <div class="swiper-slide"><img src="https://placehold.jp/150x150.png"
              alt=""></div>
        <div class="swiper-slide"><img src="https://placehold.jp/150x150.png"
              alt=""></div>
        <div class="swiper-slide"><img src="https://placehold.jp/150x150.png"
              alt=""></div>
      </div>
      <div class="swiper-custom-fraction js-custom-fraction"> <span class="js-currentNum">1</span>/<span class="js-Maxnum"></span> 
      </div>
      <div class="swiper-pagination"></div>
    </div>
  </div>
</div>

このような感じです。

swiper-pagination を swiper-container に入れていないのはスライド画像の下に、ページネーションを配置したいからです。

※ v.7 以降の場合は swiper-wrapper に入れていないのは

画像の上に表示する場合は、 swiper-container に入れて、一番外側のdiv要素を削除でOKです。

※ v.7 以降の場合は swiper-wrapper に入れてから、一番外側の div要素 を削除です

通常と違う点は以下の部分

<div class="swiper-custom-fraction js-custom-fraction">
 <span class="js-currentNum">1</span>/<span class="js-Maxnum"></span>
</div>

この部分は、自作する fraction 部分に使用します。

 

JavaScriptの準備

Swiperを使用するためのJavaScriptを記述します。

/*
 *  maxSlideNum スライドの最大枚数を入れる変数
 *  thisSlideIndex 現在のスライド番号
 */
let maxSlideNum = 0,
  thisSlideIndex = 0;
new Swiper(".swiper-container", {
  loop: true,
  centeredSlides: true,
  slidesPerView: 1,
  speed: 500,
  spaceBetween: 300,
  pagination: {
    el: ".swiper-pagination",
    clickable: true,
  },
  on: {
    init: function () {
      // Swiper起動時に実行される
      let slideNum = []; // スライドの最大枚数を取得するための配列

      /*
        下記の繰り返しで swiper-slide の data属性に付与されている swiper-slide-index を取得して
        配列に格納していく、 Math.maxで配列の中に格納されている数値の中で一番数が大きいものを maxSlideNum に入れる
      */
      let slideLength = document.querySelectorAll('.swiper-container .swiper-slide').length;
      // loop が true かチェックする
      // loop が true の場合、loopedSlidesが1になるのでこの分岐で確認が出来る false の場合は undefined が返ってくる
      if (this.loopedSlides) {
        for (let i = 0; i < slideLength; i++) {
          slideNum.push(document.querySelector('.swiper-container').getElementsByClassName('swiper-slide')[i].dataset.swiperSlideIndex);
          // v7 以降の場合は .swiper-wrapper
          maxSlideNum = Math.max(...slideNum) + 1;
        }
      } else {
        maxSlideNum = slideLength;
      }
      // スライドの最大枚数を出力
      document.querySelector('.js-Maxnum').innerHTML = maxSlideNum;

      // 最初の数値を出力(スライドの初期位置が違う場合は、ここを変更する)
      document.querySelector('.js-currentNum').innerHTML = 1;
    },
    transitionStart: function () {
      /* 
       * スライドが切り替わった時に実行される
       * インデックスは 0 スタートなので 1 を足した数値にする
       */
      thisSlideIndex = [].slice.call(document.querySelector('.swiper-pagination').querySelectorAll('.swiper-pagination-bullet')).indexOf(document.querySelector('.swiper-pagination-bullet-active')) + 1;
      document.querySelector('.js-currentNum').innerHTML = thisSlideIndex;
    },
  }
});

 

SwiperはjQuery依存が無いので、このソースコードはjQueryを使用していません。

ただ、もちろんjQueryを使用している場合はjQueryでセレクタの指定が可能です。

(セレクタの指定やindexなどを取るときはjQueryの方が、おそらく楽かもしれません。)

このソースの処理としては…

  1. Swiperを起動させる
  2. 起動時に loop が true かどうかのチェックを行う
  3. loop が true の場合、swiper-slideに data属性 swiper-slide-index が付与されるのでその数値を配列に格納
  4. 配列の中で、一番大きな数値 +1 がスライドの総枚数になるのでそれを最大値として設定
  5. loop が false の場合、単純に swiper-slide の総数が最大値になるので、 length を設定
    (HTML側にも最初から初期値(1)を書いてますが、初期値を起動時に出力しているのは、Swiper起動時に transitionStart が起動し、0が入ることがあるからです。)
  6. transitionStart 後、スライドが移動開始した時に swiper-slide-active のついた data属性 swiper-slide-index の数値に1を足した数値に変更させる

これで完了です。

まとめ

transitionStartで上手くいかないという方は、transitionEndに変えてみたり、イベントを変更してみてください。

イベント一覧はSwiperの公式ページ記載があります。

英語ですが、このページを元に再検索したり、このままGoogle翻訳で見てみたりしても結構わかります。

Swiper API

 

久しぶりのブログでしたが、もし、Swiperでこういうことできないのかな?と思って検索してこのページを見てくれてる人の役に立つと嬉しいです。

自分が検索したときに、検索ワードが悪かったのか、単純に記事が無いのか見つけることが出来なかったので…

なんて検索したら本当に難しいですよね。

「Swiper ページネーション 数字」とかで検索しても、同時に出すというよりもページネーションを数値に変更する方法などの方が出るので、キーワードが本当に難しい…

今回のJavaScriptは多分もっとスマートに書けると思います、実装時はjQueryを使用したのでそれをとりあえず忘れないうちにと純粋なJavaScriptでバタバタと書き直したので長くなってます。
(という言い訳です)

時間があったら書き直します。(という風に前も書いて書き直してない記事があるのは気のせいということにしてください。)