Swiper | スライド番号と総スライド枚数の間にプログレスバーを導入してみた

Swiperにてスライド番号と総スライド枚数の間にプログレスバーを導入してみた

JavaScriptのスライダーライブラリであるSwiperにおいて、ページネーションをカスタマイズする方法をご紹介しています。

今回は、現在表示中のスライド番号と総スライド枚数をそれぞれ表示し、その間にプログレスバーを実装してみました。

次のスライドに切り替わるまでの時間を視覚的に把握できるようになるのと、ちょっとしたアニメーションですが、Webサイトがリッチになります。

目次

ページネーションにプログレスバーを導入した例

今回実装したのはこちらです。

スライダーの右下にページネーションを配置しています。

左側に現在のスライド番号、右側に総スライド枚数を表示し、その間に次のスライドに切り替わるまでのラインアニメーションを実装しています。

ざっくりとした実装方法は、次の通りです。

  1. スライド番号と総スライド枚数の表示:Swiperのfractionを使用
  2. プログレスバーのHTML:SwiperのrenderFractionで要素を追加
  3. ラインアニメーション:CSSで表現

コードの見本

SwiperをCDNの形式でindex.html内で読み込んでいます。

headタグ内

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

bodyタグの終了直前

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

index.html

<div class="wrapper">
    <div class="swiper lineAnimationSlider">
        <div class="swiper-wrapper">
            <div class="swiper-slide"><img src="./images/01.jpg" alt="サンプル画像"></div>
            <div class="swiper-slide"><img src="./images/02.jpg" alt="サンプル画像"></div>
            <div class="swiper-slide"><img src="./images/03.jpg" alt="サンプル画像"></div>
            <div class="swiper-slide"><img src="./images/04.jpg" alt="サンプル画像"></div>
            <div class="swiper-slide"><img src="./images/05.jpg" alt="サンプル画像"></div>
        </div>
    </div>
    <div class="swiper-pagination"></div>
</div>

style.css

/* ==========================
  画像サイズ調整
========================== */
.swiper-slide {
  height: auto;
}

.swiper-slide img {
  height: 100%;
  width: 100%;
}

/* ==========================
  paginationの位置を調整
========================== */
.wrapper {
  position: relative;
}

.swiper-horizontal>.swiper-pagination-bullets,
.swiper-pagination-bullets.swiper-pagination-horizontal,
.swiper-pagination-custom,
.swiper-pagination-fraction {
  bottom: -30px;
}

/* ==========================
  fractionのカスタマイズ
========================== */
.swiper-pagination-fraction {
  font-size: 12px;
  font-weight: 600;
  color: #1a1b1b;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  position: absolute;
  z-index: 1;
}


/* ==========================
  ラインアニメーションをCSSで表現
========================== */
.swiper-pagination-fraction .border {
  width: 70px;
  height: 1px;
  margin: 0 8px;
  background-color: #ddd;
  position: relative;
}

.swiper-pagination-fraction .border span {
  position: absolute;
  top: 0;
  left: 0;
  display: inline-block;
  width: 100%;
  height: 100%;
  background-color: #1a1b1b;
  transform: scaleX(0);
  transform-origin: left center;
  transition-timing-function: linear;
}

.swiper-pagination.is-active .border span {
  transform: scaleX(1);
  transition: transform 3.85s linear;
}

script.js

const lineAnimationSlider = new Swiper('.lineAnimationSlider', {
    loop: true,
    slidesPerView: 3,
    spaceBetween: 20,
    centeredSlides: true,
    autoplay: {
        delay: 4000,
        disableOnInteraction: false,
    },
    speed: 1500,
    pagination: {
        el: '.swiper-pagination',
        type: 'fraction',
        renderFraction: function (currentClass, totalClass) {
            return '<span class="' + currentClass + '"></span>' + '<span class="border js-border"><span></span></span>' + '<span class="' + totalClass + '"></span>';
        }
    },
    on: {
        init: function () {
            setTimeout(() => {
                const pagiNation = document.querySelector('.swiper-pagination');
                pagiNation.classList.add('is-active');
            }, 100);
        },
        slideChangeTransitionStart: function () {
            const border = document.querySelector('.js-border span');
            if (border) {
                border.style.transform = 'scaleX(0)';
                border.style.transitionDuration = '0s';
            }
        },
        slideChangeTransitionEnd: function () {
            const border = document.querySelector('.js-border span');
            if (border) {
                border.style.transform = 'scaleX(1)';
                border.style.transitionDuration = '4000ms';
            }
        },
    },
});

コードの解説

今回使用したSwiperのオプションについて解説します。

paginationオプション

pagination: {
    el: '.swiper-pagination',
    type: 'fraction',
    renderFraction: function (currentClass, totalClass) {
        return '<span class="' + currentClass + '"></span>' + '<span class="border js-border"><span></span></span>' + '<span class="' + totalClass + '"></span>';
    }
},

type: 'fraction'を指定し、現在のスライド番号と総スライド枚数を表示しています。

fractionは日本語で「分数」です。
今回は表示形式をカスタマイズしていますが、デフォルトでは「現在のスライド番号 / 総スライド枚数」のように分数でページの情報が表示されます。

次にrenderFraction:パラメータで、fractionで出力されるHTMLを上書きしています。

具体的には、現在のスライド番号と総スライド枚数の間にspanタグを2つ挿入しています。外側のspanタグにはborderクラスとjs-borderクラスをつけています。

onオプション

on: {
    init: function () {
        setTimeout(() => {
            const pagiNation = document.querySelector('.swiper-pagination');
            pagiNation.classList.add('is-active');
        }, 100);
    },
    slideChangeTransitionStart: function () {
        const border = document.querySelector('.js-border span');
        if (border) {
            border.style.transform = 'scaleX(0)';
            border.style.transitionDuration = '0s';
        }
    },
    slideChangeTransitionEnd: function () {
        const border = document.querySelector('.js-border span');
        if (border) {
            border.style.transform = 'scaleX(1)';
            border.style.transitionDuration = '4000ms';
        }
    },
},

init イベント

スライダーが初期化されたときの処理を記述しています。処理内容は、初期化の100ミリ秒後にswiper-paginationの要素に、is-activeクラスを付与しています。

slideChangeTransitionStart イベント

スライド切り替えのトランジションが開始されたときの処理を記述しています。処理内容は、borderの要素の中のspanタグのスタイルを変更しています。

slideChangeTransitionEnd イベント

スライド切り替えのトランジションが完了したときの処理を記述しています。処理内容は、borderの要素の中のspanタグのスタイルを変更しています。

spanタグのスタイル変更内容
  • スライド切り替えのトランジション開始時:scaleX(0)、アニメーション時間0秒
  • スライド切り替えのトランジション完了時:scaleX(1)、アニメーション時間4000ミリ秒

以上です。最後までお読みいただきありがとうございました!

全く同じ要件の実装は少ないかもしれませんが、今回紹介したオプションを使用することで表現の幅がグッと広がるかと思います。

ちなみに私は今回のような地味で誰も気づかないようなアニメーションが好きで、自らのポートフォリオにも導入しています。

目次