【PR】を含みます。

フロントエンド

【Swiper.js】ループ付きスライダーの前後ボタンの切り替え速度を調整する方法

Swiper.js ループ付きスライダーの前後ボタンの切り替え速度を調整する方法

「Swiper.js」は、洗練されたスライダーを簡単に実装できる人気のJavaScriptライブラリです。

しかし、ループ機能を使っている場合、前後ボタンをクリックした時のスライド切り替え速度が思ったより遅く感じることがあります。

本記事では、そんなSwiper.jsのループ付きスライダーにおいて、ナビゲーションボタン操作時の切り替え速度を調整する方法をわかりやすく解説します。

デモやサンプルコードも交えて紹介しますので、Swiperの使い勝手をさらに高めたい方はぜひ参考にしてください。

POINT
  • 「swiper.js」のバージョンについて
    v11のCDNを使用

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css">

    <script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>

    最新のCDNバージョンは、以下公式サイトでご確認いただけます。

    https://swiperjs.com/get-started#use-swiper-from-cdn

前後ボタンのクリック時の切り替え速度を調整する理由

Swiper.jsでループをさせてない場合、オプションにrunCallbacksOnInit: trueを設定することで、前後ボタンクリック時、スライドを即時切り替えることができます。

しかし、ループさせている場合、スライドの切り替えが完了するまで前後ボタンをクリックしても反応しなくなります。

特にスライドの切り替え速度(speed)を遅く設定している場合に目立ちます。

【サンプル】スライドの切り替えが完了するまで前後ボタンが反応しない場合の例

Slide 1
Slide 2
Slide 3
Slide 4
Slide 5

【サンプルコード】スライドの切り替えが完了するまで前後ボタンが反応しない場合の例

別途、Swiperを使用するためのライブラリを読み込む必要があります。

※以下のコードだけでは、swiperは起動しません。

HTML
Copy
<div class="swiper-sample">
  <div class="swiper-wrapper">
    <div class="swiper-slide">Slide 1</div>
    <div class="swiper-slide">Slide 2</div>
    <div class="swiper-slide">Slide 3</div>
    <div class="swiper-slide">Slide 4</div>
    <div class="swiper-slide">Slide 5</div>
  </div>
  <!-- ナビゲーションボタン -->
  <div class="swiper-button-next"></div>
  <div class="swiper-button-prev"></div>
</div>
CSS
Copy
.swiper-sample {
  position: relative;
  overflow: hidden;
}
.swiper-wrapper .swiper-slide {
  height: 150px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.swiper-slide {
  background-color: #fff0f0;
}
.swiper-sample .swiper-button-next,
.swiper-sample .swiper-button-prev {
  width: 40px;
  height: 40px;
  border-radius: 100%;
  background: #f09896;
  top: 50%;
}
.swiper-sample .swiper-button-next:after,
.swiper-sample .swiper-button-prev:after {
  color: #fff;
  font-size: 15px;
}
JavaScript
Copy
(function() {
  let speed = 4000;
  const swiperSample = new Swiper('.swiper-sample', {
    loop: true,
    slidesPerView: 2,
    spaceBetween: 30,
    speed: speed, // スライド切り替え速度
    autoplay: {
      delay: 6000, // 切り替え間隔(ミリ秒)
      disableOnInteraction: false, // ユーザー操作後も自動再生を継続
    },
    navigation: {
      nextEl: '.swiper-sample .swiper-button-next',
      prevEl: '.swiper-sample .swiper-button-prev',
    },
  });
})();

【サンプル】前後ボタンの切り替えを即時できるように調整

Slide 1
Slide 2
Slide 3
Slide 4
Slide 5

【実装コード】前後ボタンの切り替えを即時できるように調整

別途、Swiperを使用するためのライブラリを読み込む必要があります。

※以下のコードだけでは、swiperは起動しません。

HTML
Copy
<div class="swiper">
  <div class="swiper-wrapper">
    <div class="swiper-slide">Slide 1</div>
    <div class="swiper-slide">Slide 2</div>
    <div class="swiper-slide">Slide 3</div>
    <div class="swiper-slide">Slide 4</div>
    <div class="swiper-slide">Slide 5</div>
  </div>
  <!-- ナビゲーションボタン -->
  <div class="swiper-button-next"></div>
  <div class="swiper-button-prev"></div>
</div>
CSS
Copy
.swiper {
  position: relative;
  overflow: hidden;
}
.swiper-wrapper .swiper-slide {
  height: 150px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.swiper-slide {
  background-color: #fff0f0;
}
.swiper .swiper-button-next,
.swiper .swiper-button-prev {
  width: 40px;
  height: 40px;
  border-radius: 100%;
  background: #f09896;
  top: 50%;
}
.swiper .swiper-button-next:after,
.swiper .swiper-button-prev:after {
  color: #fff;
  font-size: 15px;
}
JavaScript
Copy
(function() {
  let speed = 4000;
  let clickNavSpeed = 500; // ナビゲーションクリック時のスライド切り替え速度
  let slidesPerGroup = 1; // 一度にスライドさせる枚数
  const swiper = new Swiper('.swiper', {
    loop: true,
    slidesPerView: 2,
    slidesPerGroup: slidesPerGroup,
    spaceBetween: 20,
    speed: speed, // スライド切り替え速度
    autoplay: {
      delay: 6000, // 切り替え間隔(ミリ秒)
      disableOnInteraction: false, // ユーザー操作後も自動再生を継続
    },
  });
  let clickFlag = false;
  let isSliding = false;
  // 前へボタン
  document.querySelector('.swiper .swiper-button-prev').addEventListener('click', () => {
    adjust_slide('prev');
  });
  // 次へボタン
  document.querySelector('.swiper .swiper-button-next').addEventListener('click', () => {
    adjust_slide('next');
  });
  swiper.on('slideChangeTransitionStart', function() {
    isSliding = true;
    if (clickFlag) {
      swiper.wrapperEl.style.transition = clickNavSpeed + 'ms';
    }
  });
  swiper.on('slideChangeTransitionEnd', function() {
    isSliding = false;
    if (clickFlag) {
      clickFlag = false;
      swiper.update();
      swiper.autoplay.start();
    }
  });
  function adjust_slide(p) {
    const swiperTransform = swiper.wrapperEl.style.transform.match(/translate3d\((-?\d+\.?\d*)px, (-?\d+\.?\d*)px, (-?\d+\.?\d*)px\)/);
    if (swiperTransform && isSliding && !clickFlag) {
      // 現在のtranslateを取得
      const getTranslate = swiper.getTranslate();
      // アニメーションの停止
      swiper.setTranslate(getTranslate);
      swiper.setTransition(0);
      let x; // 次の位置の計算
      if (p === 'prev') {
        x = parseFloat(swiperTransform[1]) + getFullWidth(swiper.slides[0]) * slidesPerGroup;
      } else {
        x = swiperTransform[1];
      }
      setTimeout(() => {
        swiper.wrapperEl.style.transition = clickNavSpeed + 'ms';
        swiper.wrapperEl.style.transform = 'translate3d(' + x + 'px, 0px, 0px)';
      }, 0);
      if (p === 'prev') {
          // Swiper の状態を手動で更新
          swiper.activeIndex -= slidesPerGroup;
          // ループ処理のための修正
          if (swiper.activeIndex < 0) {
            swiper.activeIndex = swiper.slides.length - slidesPerGroup * 2; // ループ時の補正
          } else if (swiper.activeIndex >= swiper.slides.length - slidesPerGroup) {
            swiper.activeIndex = slidesPerGroup; // ループ時の補正
          }
          // realIndex` を手動で再計算
          swiper.realIndex = swiper.activeIndex % swiper.slides.length;
          // Swiper の内部状態を更新
          clickFlag = true;
          setTimeout(() => {
          swiper.emit('slideChangeTransitionEnd');
        }, clickNavSpeed);
        return;
      }
      clickFlag = true;
      return;
    }
    // アニメーションが発生していない場合、通常の動作
    clickFlag = true;
    if (p === 'prev') {
      swiper.slidePrev();
    } else {
      swiper.slideNext();
    }
  }
  function getFullWidth(element) {
    const style = window.getComputedStyle(element);
    const marginLeft = parseFloat(style.marginLeft);
    const marginRight = parseFloat(style.marginRight);
    const totalWidth = element.offsetWidth + marginLeft + marginRight;
    return totalWidth;
  }
})();

注意事項

  • Swiper.jsのバージョンによっては動作が影響を受ける可能性があります。
  • Swiper.jsのオプション(設定項目)によっては動作が影響を受ける可能性があります。
  • Swiper.jsに対して独自のJavaScriptカスタマイズを追加した場合、Swiper.jsの更新やオプション設定の変更によって動作が影響を受ける可能性があります。

まとめ

Swiper.jsのループ付きスライダーは便利ですが、前後ボタンの切り替え速度が遅く感じることもあります。

本記事で紹介した方法を使えば、ナビゲーションボタンのレスポンスを自在に調整でき、より快適なユーザー体験を実現できます。

設定を工夫して、自分のサイトや用途に合った最適なスライダーに仕上げてみてください。

Swiperのバージョンやカスタムの内容によっては動作が異なる場合もあるため、実装後は必ず動作確認を行いましょう。

-フロントエンド
-,