swiperでワンスクロールページを作成し詰まった点

javascript 2021/10/04 2021/12/27

今回swiper.jsを使ってワンスクロールページを作る機会があったのですが、
思ったより詰まった部分が多く、忘れそうなのでメモします。

そもそもSwiperとはスライダープラグインのことで、slickやbxsliderに似ていますが
jQueryに依存していないという特徴があります。主に、カルーセルスライダーなどで使うことが多そうですが
今回はそれを利用して、ワンスクロールのページを作成しました。
最初に完成したデモがこんな感じ。

DEMOサイト

特徴としては1ページに挙動の違う2つのスライダーを置いたり、スクロールイベントを発生させたりスマホ画面では片方のswiperをオフにしたり、という点です。
今回やりたかった挙動はほとんどswiperの機能で表現することができました。

1. Swiperでワンスクロールのページを作る時の基本

Swiperの導入方法に関しては省きます。

今回の最終的なコードは下記になります。CSSに関してはswiper部分のみです。

See the Pen
by HT-Web-Labon (@ht-web-labon)
on CodePen.

ちょっとわかりづらいので1つずつ見ていきます。

今回はワンスクロールページの中に普通のスライダーも入れているため、swiperで2つ設定を作っています。

/* ワンスクロールページ用swiper */
swiper = new Swiper(".slider", {
direction: "vertical",
slidesPerView: 1,
speed: 1000,
mousewheel: true,
});
/* TOP SLIDER用swiper */
TopSlider = new Swiper(".top_slider", {
loop: true,
direction: "horizontal",
slidesPerView: 1,
speed: 1500,
effect: "effect",
autoplay: {
delay: 3000,
},
});

ワンスクロールページの設定は上の.sliderクラスに設定しています。

direction: "vertical",
slidesPerView: 1,

上記の設定が縦方向に1枚ずつ表記という意味になります。

ここでのCSSでheight: 100vhを親要素に設定し、子要素はheight: 100%に設定しています。

ちなみに横方向の一般的なスライダーはdirection: “horizontal”となります。

2. スクロールした際の発火の方法(クラス付与)

DEMOページを見ると分かりますが、今回は1ページ目から2ページ目に移動した際に、サイドバーとトップに戻るリンクを表示させるようにしています。

最初はjavascriptでscrollによってイベントを発火させようと思ったのですが、swiperの挙動的にスライド変更はスクロールとみなされないようで全くうまくいきませんでした。

調べてみたところ、なんとSwiperは独自のオプションが多彩でスライドが切り替わった時のイベントも独自のコードで実装できるとのこと!すごい!それがこちら。

swiper = new Swiper(".slider", {
  direction: "vertical",
  slidesPerView: 1,
  speed: 1000,
  mousewheel: true,
   on: {
  // 切り替わりのアニメーションが開始した時
    slideChangeTransitionStart: function () {
     swipe_action();
    },
   },
});

上記のslideChangeTransitionStartというのが、slideが変わった時という指定になります。

そしてswipe_action();の内容を後述します。

function swipe_action() {
 const target = document.getElementById("side_menu");
 const toTop = document.getElementById("toTop");
 if (swiper.activeIndex == 0) { 
  target.classList.remove("fixed");
  toTop.classList.remove("fixed");
 }
 if (swiper.activeIndex == 1) {
  target.classList.add("fixed");
  toTop.classList.add("fixed");
 }
};

上記ではサイドメニューとトップに戻るリンクそれぞれに定数を設定し、

swiperのスライドが2枚目になった時にそれぞれに.fixedのクラスを付与、1枚目に戻った時に.fixedクラスがあればそれをリムーブしています。

3. メニューからのリンク

次は上記で作ったサイドメニューから、スライドごとにリンクをつける場合。

ページ内リンクとなりますが、一般的な<div id=”page01″></div>のようにラベルを設定して飛ばすことができません。

そこで、若干無理矢理ですが、javascriptの方で「このリンクをクリックしたらここへ飛ぶ」というように指示を書いてしまいます。

$(".link01").click(function () {
 swiper.slideTo(0, 3000);
});
$(".link02").click(function () {
 swiper.slideTo(1, 3000);
});
$(".link03").click(function () {
 swiper.slideTo(2, 3000);
});
$(".link04").click(function () {
 swiper.slideTo(3, 3000);
});

HTMLではサイドメニューのリンクにした部分をタグで覆い、class付与しています。

<ul>
<li><span class="link01">TOP</span></li>
<li><span class="link02">PAGE2</span></li>
<li><span class="link03">PAGE3</span></li>
<li><span class="link04">DONE!</span></li>
</ul>

無理矢理感が滲み出ていますが.link01をクリックしたらスライド1枚目へと行った感じです。

swiper.slideTo(0, 3000);

変数0はスライド1枚目へ飛ぶということで、3000は飛ぶスピードになります。

これですと、リンクごとにスライドの位置を指定することができます。(もう少し良い方法あったら教えてください…)

4. スマホでswiperを解除する方法

最後に、スマホ画面でワンスクロールページを解除する方法です。

下記のように設定しました。

/* Swiperのためのメディアクエリ */
function swiperMode() {
 let smartphone = window.matchMedia("(min-width: 0px) and (max-width: 800px)");
 let desktop = window.matchMedia("(min-width: 800px)");
 
 // デスクトップ(PC)の場合はswiperをオン
 if (desktop.matches) {
  if (!init) {
   init = true;
   swiper = new Swiper(".slider", {
    /* ///////略///////// */
   }
  }
}
// スマートフォンの際はswiper.destroy()で解除
else if (smartphone.matches) {
 if (init) {
  swiper.destroy();
  init = false;
 }
}
/* ロードした際に画面幅を読み取る */
window.addEventListener("load", function () {
 swiperMode();
});
/* リサイズした時も画面幅を読み取る */
window.addEventListener("resize", function () {
 swiperMode();
});

上記のように、ワンスクロールページ用のSwiperに設定したら、うまくいきました。

5. まとめ

試行錯誤して苦労した部分も多かったですが、swiperの機能を利用するとこんなに便利にワンスクロールページができるということに驚きました。

一回オプションなども作ってしまえば今後似たようなページもすぐ作りやすいはず。

ぜひワンスクロールページを作成する際は、swiperを活用してみてください。

Haruka

文系コーダー/通訳案内士(韓国語) javascript/php/webデザインを日々勉強中。 趣味は韓国語とゲーム。