【Swiper】流れ続けるモーダルスライダー〜矢印操作とモーダル開閉制御〜

こんにちは〜お久しぶりです。

エンジニア

カトリーヌ

もう4月・・・早すぎる・・・🥺

エンジニア

カトリーヌ

さて、Swiperで無限に流れ続けるモーダルスライダーを作りたい!
でも・・・モーダルを開いたらスライダーが止まってほしい・・・!
しかも!閉じたあとに“どこにいたっけ?”ってならずに、ちゃんと開いた場所から再開したい!
さらに!!見たいコンテンツの位置にスムーズに移動できたら最高!

そんな理想のスライダーを実装してみました

DEMO

さっそく完成版はこちらです。

See the Pen
【Swiper】流れ続けるスライダー&矢印で操作
by Catherine (@ikuradonburi)
on CodePen.

※Swiperの基本的な実装方法については省略します。本記事では、無限ループ+モーダル連携にフォーカスして解説します
※本記事では簡易的なモーダルを使用しています。必要に応じて、デザインや挙動を自由にカスタマイズしてください!

コードの説明

基本的な実装は省略して、ポイントとなる箇所のみ説明します。

流れ続けるスライダー

Swiperの autoplay 設定

delay: 0 にすることで、途切れなくスライドし続ける動きになります。


autoplay: {
  delay: 0, // 途切れずに流れ続ける
  disableOnInteraction: false, // ユーザー操作後も自動再生を継続
},

CSSの transition-timing-function: linear;

linear を指定することで、速度が一定になり、なめらかに流れ続けるようになります。


.list {
  transition-timing-function: linear;
}

矢印のよる操作


document.querySelector('.swiper-button-prev').addEventListener('click', function () {
  slide.autoplay.stop(); // 一時停止
  slide.slideTo(slide.activeIndex - 2, 1000); // 1枚前へスライド
  restartAutoplay();
});

  • slide.autoplay.stop();でスライドの動きを止める
  • slide.slideTo(slide.activeIndex - 2, 1000);でスライドを移動 ※1
  • restartAutoplay();で自動再生を再開

    function restartAutoplay() {
      setTimeout(() => {
        slide.autoplay.start();
      }, 1000);
    }

次のスライドに移動する.swiper-button-next でも使用するので関数化しています。

すぐ再開すると操作性が悪くなるので、1秒空けています。

※1 -1だと挙動が不安定だったため、-2にしています。
.swiper-button-nextではslide.slideTo(slide.activeIndex + 1, 1000);となります。

これで無限に流れ続けながら、矢印で移動が可能になります。

モーダルを開いた時に動きを止める


    if (modal.style.display === "block") {
      
        const activeSlide = document.querySelector('.swiper-slide-active');

        // 現在のスライドの幅 + 左右マージンを取得
        const activeSlideStyle = window.getComputedStyle(activeSlide);
        const slideWidth = activeSlide.offsetWidth;
        const marginLeft = parseFloat(activeSlideStyle.marginLeft) || 0;
        const marginRight = parseFloat(activeSlideStyle.marginRight) || 0;
        const totalSlideWidth = slideWidth + marginLeft + marginRight;

        // スライド位置補正
        const translate = slide.getTranslate();
        const slideOffset = -totalSlideWidth - (translate % totalSlideWidth);
        const slideMoveDuration = slideOffset / -slideWidth;

        slide.setTranslate(translate + slideOffset);
        slide.setTransition(4000 * slideMoveDuration); // スライドの速度を調整
  
        modal.style.display = "none"; //モーダルを非表示
    } else {
        // 現在のスライド位置を取得し、即座に停止
        const currentSlidePosition = slide.getTranslate();
        slide.setTranslate(currentSlidePosition);
        slide.setTransition(0);
        modal.style.display = "block"; //モーダルを表示
    }

モーダルが表示された時

  • slide.getTranslate();スライドの現在の位置を取得
  • slide.setTranslate(currentSlidePosition);取得した位置に固定
  • slide.setTransition(0);スライドのアニメーションを無効化

モーダルが非表示になった時

  • window.getComputedStyle(activeSlide);クリック時に .swiper-slide-active に適用されているスタイル情報を取得する
  • activeSlide.offsetWidth;アクティブ要素の幅を取得
  • parseFloat(style.marginLeft) || 0; 指定されている場合文字列を数値に変換(例:10px→10)(marginRIghtも同様)
  • slideWidth + marginLeft + marginRight;マージンも含めた幅を取得
  • slide.getTranslate();スライドの現在の位置を取得
  • -totalSlideWidth - (translate % totalSlideWidth); 現在のスライド位置のズレを補正して次のスライド位置を計算
  • diff / -slideWidth;スライド位置のズレに応じて、移動時間を計算

これでモーダルを開いた際に自動再生を停止し、閉じた時に再開できます。

まとめ

Swiperを使って無限に流れ続けるモーダルスライダー を作りつつ、以下の機能を追加しました!

  • 矢印ボタンでスライド操作可能
  • モーダルを開くとスライダーが停止し、閉じると再生再開
  • モーダルを閉じた後も、開いた場所からスライドが再開

これで、「モーダルを開いて戻ったら位置が分からなくなる……」という問題を解決できました!

あとはデザインや動作の細かい調整を加えて、用途に応じてカスタマイズしてみてください!

ところで

弊社ロジカルスタジオでは、一緒に働く仲間を募集しています!
下記リンクからぜひご応募ください!