Swiperでサムネイルリスト付きのスライダーを作成する

Swiperでサムネイルリスト付きのスライダーを作成する

前回、下記の記事でSwiperでサムネイル付きのスライダーの作成を紹介しました。

Swiperでサムネイル付きのスライダーを作成するSwiperでサムネイル付きのスライダーを作成する

前回はサムネイル側はスライダーでしたが、今回はサムネイル側はリスト形式で表示するパターンです。

制作物をcodepenで見る

See the Pen swiper with thumbnail slider2 by takblog (@blanks-site) on CodePen.

前回とは違って、リスト形式で表示するパターンだということが確認できるかと思います。

今回はSwiperのpaginationオプションを使って、サムネイルリストを作っています。

以下が今回のhtmlになりますが、サムネイル画像を表示する箇所は<div class="thumblist"></div>の要素内です。

<div class="swiper-container">
  <div class="swiper-wrapper">
    <div class="swiper-slide"><img src="https://takblog.site/wp-content/themes/takblog/assets/img/blanks/post19_1.jpg" alt=""/></div>
    <div class="swiper-slide"><img src="https://takblog.site/wp-content/themes/takblog/assets/img/blanks/post19_2.jpg" alt=""/></div>
    <div class="swiper-slide"><img src="https://takblog.site/wp-content/themes/takblog/assets/img/blanks/post19_3.jpg" alt=""/></div>
    <div class="swiper-slide"><img src="https://takblog.site/wp-content/themes/takblog/assets/img/blanks/post19_4.jpg" alt=""/></div>
    <div class="swiper-slide"><img src="https://takblog.site/wp-content/themes/takblog/assets/img/blanks/post19_5.jpg" alt=""/></div>
    <div class="swiper-slide"><img src="https://takblog.site/wp-content/themes/takblog/assets/img/blanks/post19_6.jpg" alt=""/></div>
  </div>
  <div class="thumblist"></div>
</div>

見て分かるように、<div class="thumblist"></div>の要素内には最初の段階では何も入っていません。

.swiper-slide 内の画像を取得してきて、サムネイルリストを作っているので、毎回サムネイルリストのhtmlの記述を変える必要はないです。

またサムネイル画像をクリックしてもメインスライダーの画像が切り替わるような仕様にもしてあるので、使い勝手も良いものだと思います。

ここで使っているswiperのバージョンは4.5.0です。
swiperのバージョンによってはオプションの書き方が違うので、注意してください。

制作コード

javascriptのコードは以下のものです。

コードをクリップボードにコピー
const thumbClass = 'thumblist-item';
const mytap = window.ontouchstart === null?"touchstart":"click";

const mySwiper = new Swiper('.swiper-container', {
  speed: 1500,
  autoplay:{
    delay:2000
  },
  pagination:{
    el:'.thumblist',
    type:'custom',
    renderCustom: function (swiper, current, total) {
      const slides = swiper.slides;
      let html = '';
      for( let i = 0 ; i < total; i++ ){
        if( current == i+1 ){
          html = html + `<div class="${thumbClass} current" data-slideto="${i}">${slides[i].innerHTML}</div>`;
        }else{
          html = html + `<div class="${thumbClass}" data-slideto="${i}">${slides[i].innerHTML}</div>`;
        }
      }
      return html;
    }
  }
});

const clickThumbs = (()=>{
  const thumbItems = document.getElementsByClassName(thumbClass);
  for(let i = 0; i < thumbItems.length ; i ++){
    thumbItems[i].addEventListener(mytap,((e)=>{
      let index = e.currentTarget.dataset.slideto;
      mySwiper.slideTo(index, 1500, true);
      // autoplayオプションを使わない場合は、以下をコメントアウトをする
      setTimeout(mySwiper.autoplay.start,3000);
    }),false);
  }
});

clickThumbs();
mySwiper.on('slideChange',clickThumbs);

簡単に中身を説明していきます。

コードをポップアップで見る

1~2行目

thumbClass はサムネイルリストのサムネイル画像を囲むdivタグのclassです。

mytap はタッチできるデバイスでは、touchstartを、それ以外はclickを入れています。
サムネイル画像をクリックしてメインスライダーが切り替わるときのイベントのときにmytapを使っています。

4~25行目:mySwiper

今回はpaginationの箇所が肝ですので、10行目以降を説明しています。

elオプションはpaginationにしたい要素のclassを設定するので、今回は '.thumblist' です。(10行目)

typeオプションは今回は'custom'です。
他に 'bullets', 'fraction', 'progressbar' が設定できますが、一番使うのは'bullets'かなーと思います。
そもそも今回は 'custom' でどんな風にできるかなーと思って、作ったのが発端です。

ここからが今回一番大事な箇所だと思います。

12~23行目のrenderCustomは、typeオプションが 'custom' の場合のpaginationの中身を決定するオプションです。

引数で使えるのは、swiper, current, totalの3つです。

コンソールで引数のswiperを確認したのですが、今回で言うと mySwiper の情報がたくさんあったので、これを活用すれば、色々できるな!と思いました。

currentは現在表示中のスライド番号で、totalは全スライド数です。

今回は、swiper.slides で全スライドのオブジェクトを取得して使用しています。(13行目)

15~21行目をfor文で回していますが、表示中のスライド番号と同じサムネイルアイテムには current の class を追加するようにしています。

またdata-slideto属性は、後述のclickThumbs関数で使用します。
clickThumbs関数はサムネイルをクリックすると、メインスライダーのスライドが切り替わる関数です。

slides[i] では、<div class="swiper-slide">〜</div>を取得しており、その内部のhtmlのみほしいので、slides[i].innerHTMLで取得しています。
これによりわざわざサムネイルリストのhtmlを記述する必要がなくなっています。

最後に return html; で <div class="thumblist"></div>内に、htmlを追加しています。

27~40行目:clickThumbs関数

これはサムネイルリストアイテムをクリックすると、メインスライダーのスライドも該当スライドに切り替わる関数です。

clickableオプションをtrueにして、サムネイルをクリックしてもスライドが切り替わらないので、別で関数を制作しました。

簡単に説明すると、クリックしたサムネイルのdata-slideto属性を取得して、その値の番号のスライドに切り替わるという仕組みです。

autoplayオプションを使用している場合、slideToメソッドを使用すると、autoplayが止まるので、setTimeoutで切り替わって数秒後にautoplayが始まるようにしています。(34行目)

最後にslideChaneイベントでclickThumbs関数を呼び出していますが、これは一度スライドが切り替わると、clickThumbs関数が上手く動かなくなったからこのようにしています。(40行目)

おそらくスライドが切り替わるたびに、renderCustomで定義した関数が動いて、そのたびにpaginationの中のhtmlが一度削除されて、再び作成されているのではないかと思いました。

一度スライドが切り替わるとバインドした要素がなくなってしまったために、上手くclickThumbs関数が動かくなってしまっていたのではないかと考えて、スライドが切り替わるたびにclickThumbs関数を呼び出すようにしました。

arrow_circle_up