今回はSwiperでサムネイル付きの連動するスライダーを作っていきます。

サムネイルがスライダーではなく、リスト形式で表示するサムネイル付きスライダーの作成の仕方は次の記事で紹介しています。

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

意外に引っかかったところがあるので、そこも含めて書いていきます。

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

制作物をcodepenで見る

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

上下のスライダーが連動して動いていることが確認できると思います。

スライダー連動のためにオプションの controller を使用しているのですが、controllerを使用するだけでは、以下のような仕様にはなりません。

  • サムネイルスライダー(上記例では下のスライダー)をクリックすると、クリックしたスライダーに変わる。
  • サムネイルスライダーをクリックして、スライドが変更された後にautoplayが始まる。
  • メインスライダー(上記例では上のスライダー)を手動で切り替えたときに、サムネイルスライダーもカレントスライドが切り替わる。

今回制作したものは上記の仕様も満たしたものです。

また使用上の注意点があります。

  • メインスライダーとサムネイルスライダーのスライド(.swiper-slide)の数は揃えてください。
  • メインスライダーのn枚目がカレントの時に、サムネイルスライダーのn枚目がカレントになるようになっています。
    それを踏まえた上で、それぞれのスライダーのスライドの並び順を決定してください。

制作コード

以下のようなマークアップで使用することを想定して、jsは組んでいるので、適宜変更して使用してください

<!-- メインスライダー -->
<div class="swiper-container main-sldier">
  <div class="swiper-wrapper">
    <div class="swiper-slide main-slide"><img src="画像パス" alt=""/></div>
    <div class="swiper-slide main-slide"><img src="画像パス" alt=""/></div>
    <div class="swiper-slide main-slide"><img src="画像パス" alt=""/></div>
    <div class="swiper-slide main-slide"><img src="画像パス" alt=""/></div>
  </div>
</div>
<!-- サムネイルスライダー -->
<div class="swiper-container thumbnail-sldier">
  <div class="swiper-wrapper">
    <div class="swiper-slide thumbnail-slide"><img src="画像パス" alt=""/></div>
    <div class="swiper-slide thumbnail-slide"><img src="画像パス" alt=""/></div>
    <div class="swiper-slide thumbnail-slide"><img src="画像パス" alt=""/></div>
    <div class="swiper-slide thumbnail-slide"><img src="画像パス" alt=""/></div>
  </div>
</div>

制作したjavascriptのコードは以下のものです。

コードをクリップボードにコピー
const mainSlider = '.main-sldier'                                        //メインスライダーのクラス名
const thumbSlider = '.thumbnail-sldier'                                  //サムネイルスライダーのクラス名
const mainSlides = document.getElementsByClassName('main-slide');        //メインスライダーのslideのクラス名
const thumbSlides = document.getElementsByClassName('thumbnail-slide');  //サムネイルスライダーのslideのクラス名
let slideChangePermit = false;

const mainSwiper = new Swiper(mainSlider,{
  loop: true,
  loopedSlides: mainSlides.length
});

const thumbSwiper = new Swiper(thumbSlider, {
  speed: 1500,
  autoplay: {
    delay: 2000
  },
  slideToClickedSlide: true,
  spaceBetween: 10,
  slidesPerView: 'auto',
  centeredSlides: true,
  loop: true,
  loopedSlides: mainSlides.length,
  controller:{
    control:mainSwiper
  }
});

for( let i = 0; i < thumbSlides.length ; i ++ ){
  thumbSlides[i].addEventListener('click',()=>{
    setTimeout(()=>{
      thumbSwiper.autoplay.start();
    },3000);
  },false);
}

mainSwiper.on('touchEnd',()=>{
  slideChangePermit = true;
});

mainSwiper.on('slideChange',()=>{
  if( slideChangePermit ){
    const current = mainSwiper.activeIndex;
    thumbSwiper.slideTo(current, 300, true); 
    setTimeout(()=>{
      thumbSwiper.autoplay.start();
      slideChangePermit = false;
    },3000);
  }
});

つまずいたところも含めて、簡単に説明していきます。

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

7~10行目:mainSwiper

メインスライダーの設定です。

loopモードで設定しています。通常、ただのloopだけだと、loopedSlidesの値を設定する必要はありません。

しかし今回はloopedSlidesを設定しないとスライドの移動量が正しくなりません。

loopedSlidesはスライド(.swiper-slide)の数の値を入れます。
可変にするために、mainSlides.length の値を入れています。

12~26行目:thumbSwiper

サムネイルスライダーの設定です。

autoplayで動くように設定しています。

今回、サムネイルスライダー側に controller オプションをつけていますが、メインスライダー側に controller オプションを付けても、連動するスライダーを作ることができると思います。

その際は他の記述箇所がだいぶ変わってきますが、1つ注意するのは
controller オプションを付けている方に autoplayオプションを付けることです。
このように設定しないと、上手く動きませんでした。

他にサムネイルスライダーの設定で気を付ける点は slidesPerView オプションです。

slidesPerViewオプションは、表示されるスライドの数を設定するオプションです。

今回は auto に設定しています。
autoに設定することで、スライドの幅をpxなどcssで指定することができるようになります。

ここで気をつけなくてはいけないのが、
slidesPerView: 'auto' かつ loop:true のときは、
loopedSlidesも設定しなければならない ということです。

loopeSlidesはスライドの数で、メインスライダーのスライドの数と合わせているので、mainSlides.length を設定しています。

Swiperを何度か使っていて思うのは、slidesPerView: 'auto' の使い方って意外に重要だなーって思います。

slideToClickedSlide オプションはクリックしたスライドをカレントにするオプションです。これをtrueにしておかないと、使い勝手が悪いので、trueにしています。

centeredSlides はカレントのスライドを真ん中に持ってくるオプションです。

28~34行目

これはサムネイルスライダーのスライドをクリックした時に実行されます。

slideToClickedSlide オプションを付けたことで、クリックしたスライドがカレントになるのはいいのですが、クリックするとautoplayが止まってしまいます。

そこでサムネイルスライダーのスライドをクリックした3秒後に、再びautoplayが始まるように設定しています。

36~49行目

ここはメインスライダーを手動で切り替えた時に実行されます。

メインスライダーを手動で切り替ても、サムネイルスライダーは連動して動いてくれませんでした。
メインスライダーのほうにも controller を付けて、色々試したのですが、上手くいかず、このような形に収まりました。

違うやり方や、Swiperに準備されているオプションを利用してもっと上手くできる方法があるなら教えていただけると助かります。


ここから説明です。
まず今回使っている touchEnd イベントと slideChange イベントを簡単に説明します。

touchEnd イベント

スライドをクリックやタッチして、マウスや指を離した時に発火するイベントです。

slideChange イベント

カレントのスライドが変わった時に発火するイベントです。

実行される流れとしては、touchEnd イベントが起こり、
slideChangePermit = true;にしてから、
slideChange イベントの中身が発火し、
最後にslideChange イベントの中で slideChangePermit = false; にしています。

最初は、touchEndイベントの中に42~47行目の記述を入れていました。

しかし、touchEndイベント直後ではまだスライドが切り替わっていないため、mainSwiper.activeIndex(カレントのスライド番号)が正しく取得ができませんでした。

そこで次に、touchEnd で発火する関数の中に、if文(41行目)なしで、40~49行目までの関数を入れていました。

slideChangeイベントはカレントのスライドが切り替わった後に発火するイベントなので、これならmainSwiper.activeIndex(カレントのスライド番号)が正しく取得できるだろうと考えたのです。

しかし一度 touchEndで発火すると、スライドが切り替わるたびに、slideChange イベントの中の関数が実行され、上手く動かなくなりました。

slideChangeイベントはスライドが切り替わるたびに発火するので、autoplayで連動して動こうが、手動で動かそうが発火してしまいます。

そこで touchEnd イベントが起こったときのみ、slideChangePermit = true にして、
slideChangeイベントの中は、slideChangePermit = true のときのみ実行されるようにしました。

一度、slideChangeイベントの中の関数を通ると、slideChangePermit = falseになるので、スライドが切り替わっても、slideChangeイベントの中の関数が繰り返し実行されることはありません。


slideChangeイベントの中身についても少し説明します。

mainSwiper.activeIndexは何度か説明しているように、カレントのスライド番号を取得します。
取得した値を current に入れています。

サムネイルスライダーの current 番目のスライドをカレントにしています。(43行目)

カレントスライドを変更した3秒後に、再びサムネイルスライダーのautoplayをスタートさせています。


以上、Swiperでサムネイル付きスライダーを作るでした!