ページネーションを直線長方形のプログレスバーにしたSwiperスライダーを実装してみる(備忘録)

今回はページネーション(画像下の丸い部分)を直線長方形のプログレスバーにしたSwiperスライダーを実装していく。

ソースは前回の記事をもとに作成している。

前回の記事はこちら

今回は下記部分を主に調整している。時間は前回の記事に合わせて5秒としている。

  • ページネーション(画像下の丸い部分)部分を横長の長方形になるよう調整
  • スライダーがアクティブになっているときの線の色、アクティブ担っていない時の線の色を調整
  • keyframesで直線長方形のプログレスバーが一定の変化で伸びていくように調整

また、円形のプログレスバーでは、JavaScript側でHTMLを生成するための記述をしたが、今回の直線長方形のプログレスバーでは単純なHTMLの構造になるため、swiperのページネーションで生成されるHTMLを利用してCSS側で調整することで対応ができるようになっている。

HTMLの記述について

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Swiperスライダー</title>
  <link rel="stylesheet" href="../reset.css">
  <link rel="stylesheet" href="https://unpkg.com/swiper@8/swiper-bundle.min.css" />
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main>
    <div class="swiperCont">
      <div class="swiper mySwiper">
        <div class="swiper-wrapper">
          <div class="swiper-slide">
            <img src="img1.jpg" />
          </div>
          <div class="swiper-slide">
            <img src="img2.jpg" />
          </div>
          <div class="swiper-slide">
            <img src="img3.jpg" />
          </div>
          <div class="swiper-slide">
            <img src="img4.jpg" />
          </div>
        </div>
      </div>
      <div class="swiper-pagination"></div>
      <div class="swiper-button-prev"></div>
      <div class="swiper-button-next"></div>
    </div>
    <section>
      <div class="ly_inner" id="menu1">
        <h2>menu1</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
    <section>
      <div class="ly_inner" id="menu2">
        <h2>menu2</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
    <section>
      <div class="ly_inner" id="menu3">
        <h2>menu3</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
    <section>
      <div class="ly_inner" id="menu4">
        <h2>menu4</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
    <section>
      <div class="ly_inner" id="menu5">
        <h2>menu5</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
  </main>
  <script src="https://unpkg.com/swiper@8/swiper-bundle.min.js"></script>
  <script src="style.js"></script>
</body>
</html>

HTMLの記述は前回の記事と同様のため、解説は省略させていただく。

CSSの記述について

@charset "utf-8";

/* ==========================
  初期設定
========================== */
*,
*::before,
*::after {
  box-sizing: border-box;
}
body {
  position: relative;
}
img {
  width: 100%;
}

/* ==========================
  swiperslider
========================== */
.swiperCont {
  /* width: 80%; */
  margin: 0 auto;
  position: relative;
}
.swiper {
  width: 100%;
}
.swiper-button-next,
.swiper-rtl .swiper-button-prev,
.swiper-button-prev,
.swiper-rtl .swiper-button-next {
  background-color: #ccc;
  border-radius: 50%;
  padding: 30px;
}
.swiper-button-next:focus,
.swiper-rtl .swiper-button-prev:focus,
.swiper-button-prev:focus,
.swiper-rtl .swiper-button-next:focus {
  outline: none;
}
.swiper-button-prev:after,
.swiper-rtl .swiper-button-next:after,
.swiper-button-next:after,
.swiper-rtl .swiper-button-prev:after {
  color: #fff;
  font-size: 24px;
}
.mySwiper {
  margin-top: 10px;
}
.mySwiper .swiper-slide {
  opacity: 0.4;
}
.mySwiper .swiper-slide-thumb-active {
  opacity: 1;
}
.swiper-horizontal>.swiper-pagination-bullets,
.swiper-pagination-bullets.swiper-pagination-horizontal,
.swiper-pagination-custom,
.swiper-pagination-fraction {
  bottom: -50px;
}

/* 直線長方形のプログレスバー */
.swiper-pagination-bullet {
  position: relative;
  width: 80px;
  height: 5px;
  border-radius: 0;
  background-color: rgba(233, 74, 28, .2);
  opacity: 1;
}
.swiper-pagination-bullet::before {
  content: "";
  position: absolute;
  display: block;
  top: 0;
  left: 0;
  width: 0;
  height: 100%;
  background-color: #c3512f;
}
.swiper-pagination-bullet-active::before {
  animation: paginationActive 5s linear forwards;
}
@keyframes paginationActive {
  100% {
    width: 100%;
    opacity: 1;
  }
}

/* ==========================
  コンテンツの中身
========================== */
.ly_inner {
  width: 100%;
  max-width: 1080px;
  margin: 100px auto;
  padding: 20px;
  background-color: #ccc;
}
.ly_inner h2 {
  font-size: 150%;
  font-weight: bold;
  margin-bottom: 30px;
}
.md_textblock>*+* {
  margin-top: 10px;
}

直線長方形のプログレスバーの記述は下記の部分にあたる。

/* 直線長方形のプログレスバー */
.swiper-pagination-bullet {
  position: relative;
  width: 80px;
  height: 5px;
  border-radius: 0;
  background-color: rgba(233, 74, 28, .2);
  opacity: 1;
}
.swiper-pagination-bullet::before {
  content: "";
  position: absolute;
  display: block;
  top: 0;
  left: 0;
  width: 0;
  height: 100%;
  background-color: #c3512f;
}
.swiper-pagination-bullet-active::before {
  animation: paginationActive 5s linear forwards;
}
@keyframes paginationActive {
  100% {
    width: 100%;
  }
}

ポイントは3つある。

デフォルトのページネーションについて

デフォルトのページネーションは丸く表示されるようになっている点だ。border-radiusの値を0にすることで丸みをとる必要がある。

opacityとbackground-colorについて

opacityとbackground-colorについてだ。デフォルトではopacityに0.2、backgroundに#000の値がついている。このことから、直線長方形のプログレスバーは背景(background)で見た目が作られていることがわかる。

直線長方形のプログレスバーを作成するには、この値の指定を少し工夫する必要がある。

直線長方形のプログレスバーが伸びる前の状態

直線長方形のプログレスバーがアクティブになっていない時の状態については、少し透過されて薄めの色で設定されていることが多いと思う。

通常だとopacityで透明度を調整したいところだが、背景にもopacityがかかってしまうためうまくいかない。

直線長方形のプログレスバーがリアルタイムで伸びている状態は擬似要素で対応するので、直線長方形のプログレスバーがアクティブになっている時も透明度が薄くなって反映されてしまう。この部分が個人的に実装に苦労した点である。

では、どうすればいいのかというと、下記のように設定する。

  • 直線長方形のプログレスバーのopacityの値を1に設定
  • 直線長方形のプログレスバーのbackground-colorをrgba(233, 74, 28, .2)に設定

background-colorがポイントになっていて、rgbaと指定することによって、aの部分で透明度が設定できるようになる。これにより背景に対して個別に指定ができるようになる。

直線長方形のプログレスバーがアクティブになっているときについて

直線長方形のプログレスバーがアクティブになっているときの状態は、擬似要素で対応している。

やりたいこととしては、ページを読み込んだときの最初の直線長方形のプログレスバーのメーターが0の幅から始まるようにしたい。このため、widthの値を0にしている。

続いて、background-colorの値は透明度を1にした状態にするため、#c3512fと指定した。

animationとkeyframesの設定

animationは一定の変化(linear)で5秒経過したらkeyframes指定した最後の状態(forwards)で終わるように設定した。

keyframesでは0〜100%にかけてwidthの値が100%になるように徐々に変化していく過程を設定した。

これによりページ読み込み時にアクティブになっている直線長方形のプログレスバーが5秒かけて伸びていく見た目が実装できるようになる。

JavaScriptの記述について

'use strict'
window.onload = function () {
  const swiper = new Swiper('.mySwiper', {
    loop: true,
    speed: 300,
    effect: 'fade',
    pagination: {
      el: '.swiper-pagination',
      clickable: true,
      spaceBetween: 40,
    },
    navigation: {
      nextEl: '.swiper-button-next',
      prevEl: '.swiper-button-prev',
    },
    autoplay: {
      delay: 5000,
      disableOnInteraction: false,
    },
    on: {
      slideChange: function () {
        if (this.realIndex > 0) {
          this.params.autoplay.delay = 4700
        }
      },
    },
  })
}

JavaScriptについては、前回の記事から一部分を削除しただけなので、解説は省略したい。

前回の記事はこちら

以上で実装完了だ。