Swiper.jsのページネーションをInstagram風にする

投稿日:

はじめに

Webページでカルーセルを実装するときにSwiper.jsって便利ですよね(唐突)。
最近も、とある事情でやっかいなカルーセルの実装があったのですがこのライブラリのおかげでなんとか実装できました。感謝感謝。

個人的にも便利だなぁと思ったのと、なぜか急にSwiper.jsのページネーションをInstagram(スマホアプリ版)風に出来ないかなぁと思い立ち実装してみたので、実装の経緯などを残しておこうと思います。

ソース

https://github.com/shimabox/insta-like-swiper-pagination/

デモ

https://shimabox.github.io/insta-like-swiper-pagination/

注意(まだ未完成です)

実装してみたといいつつも、全然完成形ではありません。
めちゃんこTODOがあります。
中でもページネーションの動きにアニメーションをつけないとページが変わったのかどうかが全くわからん状態なので、そこはなる早で対応したいなぁと思っています。
(例えば総数が10ページあるときに、7ページ目まで移動してきたときと7ページ目から8ページ目まで移動したときなど)

未完成なのに公開することにしたのは、TODO対応まですると絶対に公開まで時間がかかると思ったからであります。
ただ、以下にずらずらと記載した通り独特な?動きはとりあえず実装できているではないのかなと思っています。

完璧を目指すよりまず終わらせろ

Done is better than perfect.

-マーク・ザッカーバーグ

というわけで、まず実装手順からいってみたいと思います。

実装手順

  1. まずインスタグラムの動きを見てみる
  2. 動作にパターンがあるか考える
  3. パターンが見えたら実装に落とし込む

上記の流れで実装を行いました。
では、実装までの手順をつれづれと書いていきたいと思います。

インスタグラム上での動き

実際にインスタグラムのスマホアプリに画像をアップ(数年ぶりに使った!)して動作を確認しました。
※ ちなみにスマホはAndroid(Pixel3)です

5ページ(5枚)

次に進んでいった場合
総数 キャプチャ
(By Instagram.)
移動過程 移動回数
( → の数)
現在ページ 前ページ ドットの数 ドットパターン
※ パターンx.は後述
5 初期表示 0 1 0 5 パターン1. ・デフォルト
(1〜5ページ目まで一緒)
1 → 2 → 3 → 4 → 5 4 5 4 5 パターン1. ・デフォルト
(カレントが動くのみ)
前に戻っていった場合 (移動回数を – とする)
総数 キャプチャ
(By Instagram.)
移動過程 移動回数
( → の数)
現在ページ 前ページ ドットの数 ドットパターン
5 5 → 4 → 3 → 2 → 1 -4 1 2 5 パターン1. ・デフォルト
(カレントが動くのみ)

6ページ(6枚)

次に進んでいった場合
総数 キャプチャ
(By Instagram.)
移動過程 移動回数
( → の数)
現在ページ 前ページ ドットの数 ドットパターン
6 初期表示 0 1 0 6 パターン2. ・通常のドット5つ
・最後の1つが少し小さいドット
1 → 2 → 3 → 4 → 5 4 5 4 6 パターン2. ・通常のドット5つ
・最後の1つが少し小さいドット
1 → 2 → 3 → 4 → 5
→ 6
5 6 5 6 パターン3. ・先頭の1つが少し小さいドット
・通常のドット5つ
前に戻っていった場合 (移動回数を – とする)
総数 キャプチャ
(By Instagram.)
移動過程 移動回数
( → の数)
現在ページ 前ページ ドットの数 ドットパターン
6 5 → 4 -1 4 5 6 パターン2. ・通常のドット5つ
・最後の1つが少し小さいドット
5 → 4 → 3 → 2 → 1 -4 1 2 6 パターン2. ・通常のドット5つ
・最後の1つが少し小さいドット
6 → 5 -1 5 6 6 パターン3. ・先頭の1つが少し小さいドット
・通常のドット5つ
6 → 5 → 4 → 3 → 2 -4 2 3 6 パターン3. ・先頭の1つが少し小さいドット
・通常のドット5つ
6 → 5 → 4 → 3 → 2
→ 1
-5 1 2 6 パターン2. ・通常のドット5つ
・最後の1つが少し小さいドット

7ページ(7枚)

次に進んでいった場合
総数 キャプチャ
(By Instagram.)
移動過程 移動回数
( → の数)
現在ページ 前ページ ドットの数 ドットパターン
7 初期表示 0 1 0 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
1 → 2 → 3 → 4 → 5 4 5 4 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
1 → 2 → 3 → 4 → 5
→ 6
5 6 5 7 パターン5. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後の1つが少し小さいドット
1 → 2 → 3 → 4 → 5
→ 6 → 7
6 7 6 7 パターン6. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
前に戻っていった場合 (移動回数を – とする)
総数 キャプチャ
(By Instagram.)
移動過程 移動回数
( → の数)
現在ページ 前ページ ドットの数 ドットパターン
7 5 → 4 -1 4 5 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
5 → 4 → 3 → 2 → 1 -4 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
6 → 5 -1 5 6 7 パターン5. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後の1つが少し小さいドット
6 → 5 → 4 → 3 → 2 -4 2 3 7 パターン5. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後の1つが少し小さいドット
6 → 5 → 4 → 3 → 2
→ 1
-5 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
7 → 6 -1 6 7 7 パターン6. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
7 → 6 → 5 → 4 → 3 -4 3 4 7 パターン6. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
7 → 6 → 5 → 4 → 3
→ 2
-5 2 3 7 パターン5. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後の1つが少し小さいドット
7 → 6 → 5 → 4 → 3
→ 2 → 1
-6 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット

8ページ(8枚)

次に進んでいった場合
総数 キャプチャ
(By Instagram.)
移動過程 移動回数
( → の数)
現在ページ 前ページ ドットの数 ドットパターン
8 初期表示 0 1 0 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
1 → 2 → 3 → 4 → 5 4 5 4 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
1 → 2 → 3 → 4 → 5
→ 6
5 6 5 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
1 → 2 → 3 → 4 → 5
→ 6 → 7
6 7 6 8 パターン8. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後の1つが少し小さいドット
1 → 2 → 3 → 4 → 5
→ 6 → 7 → 8
7 8 7 7 パターン6. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
前に戻っていった場合 (移動回数を – とする)
総数 キャプチャ
(By Instagram.)
移動過程 移動回数
( → の数)
現在ページ 前ページ ドットの数 ドットパターン
8 5 → 4 -1 4 5 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
5 → 4 → 3 → 2 → 1 -4 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
6 → 5 -1 5 6 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
6 → 5 → 4 → 3 → 2 -4 2 3 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
6 → 5 → 4 → 3 → 2
→ 1
-5 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
7 → 6 -1 6 7 8 パターン8. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後の1つが少し小さいドット
7 → 6 → 5 → 4 → 3 -4 3 4 8 パターン8. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後の1つが少し小さいドット
7 → 6 → 5 → 4 → 3
→ 2
-5 2 3 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
7 → 6 → 5 → 4 → 3
→ 2 → 1
-6 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
8 → 7 -1 7 8 7 パターン6. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
8 → 7 → 6 → 5 → 4 -4 4 5 7 パターン6. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
8 → 7 → 6 → 5 → 4
→ 3
-5 3 4 8 パターン8. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後の1つが少し小さいドット
8 → 7 → 6 → 5 → 4
→ 3 → 2
-6 2 3 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
8 → 7 → 6 → 5 → 4
→ 3 → 2 → 1
-7 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット

9ページ(9枚)

次に進んでいった場合
総数 キャプチャ
(By Instagram.)
移動過程 移動回数
( → の数)
現在ページ 前ページ ドットの数 ドットパターン
9 初期表示 0 1 0 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
1 → 2 → 3 → 4 → 5 4 5 4 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
1 → 2 → 3 → 4 → 5
→ 6
5 6 5 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
1 → 2 → 3 → 4 → 5
→ 6 → 7
6 7 6 9 パターン9. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
1 → 2 → 3 → 4 → 5
→ 6 → 7 → 8
7 8 7 8 パターン8. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後の1つが少し小さいドット
1 → 2 → 3 → 4 → 5
→ 6 → 7 → 8 → 9
8 9 8 7 パターン6. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
前に戻っていった場合 (移動回数を – とする)
総数 キャプチャ
(By Instagram.)
移動過程 移動回数
( → の数)
現在ページ 前ページ ドットの数 ドットパターン
9 5 → 4 -1 4 5 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
5 → 4 → 3 → 2 → 1 -4 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
6 → 5 -1 5 6 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
6 → 5 → 4 → 3 → 2 -4 2 3 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
6 → 5 → 4 → 3 → 2
→ 1
-5 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
7 → 6 -1 6 7 9 パターン9. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
7 → 6 → 5 → 4 → 3 -4 3 4 9 パターン9. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
7 → 6 → 5 → 4 → 3
→ 2
-5 2 3 7 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
7 → 6 → 5 → 4 → 3
→ 2 → 1
-6 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
8 → 7 -1 7 8 8 パターン8. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後の1つが少し小さいドット
8 → 7 → 6 → 5 → 4 -4 4 5 8 パターン8. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後の1つが少し小さいドット
8 → 7 → 6 → 5 → 4
→ 3
-5 3 4 9 パターン9. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
8 → 7 → 6 → 5 → 4
→ 3 → 2
-6 2 3 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
8 → 7 → 6 → 5 → 4
→ 3 → 2 → 1
-7 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
9 → 8 -1 8 9 7 パターン6. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
9 → 8 → 7 → 6 → 5 -4 5 6 7 パターン6. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
9 → 8 → 7 → 6 → 5
→ 4
-5 4 5 8 パターン8. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後の1つが少し小さいドット
9 → 8 → 7 → 6 → 5
→ 4 → 3
-6 3 4 9 パターン9. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
9 → 8 → 7 → 6 → 5
→ 4 → 3 → 2
-7 2 3 7 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
9 → 8 → 7 → 6 → 5
→ 4 → 3 → 2 → 1
-8 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット

10ページ(10枚)

次に進んでいった場合
総数 キャプチャ
(By Instagram.)
移動過程 移動回数
( → の数)
現在ページ 前ページ ドットの数 ドットパターン
10 初期表示 0 1 0 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
1 → 2 → 3 → 4 → 5 4 5 4 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
1 → 2 → 3 → 4 → 5
→ 6
5 6 5 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
1 → 2 → 3 → 4 → 5
→ 6 → 7
6 7 6 9 パターン9. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
1 → 2 → 3 → 4 → 5
→ 6 → 7 → 8
7 8 7 9 パターン9. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
1 → 2 → 3 → 4 → 5
→ 6 → 7 → 8 → 9
8 9 8 8 パターン8. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後の1つが少し小さいドット
1 → 2 → 3 → 4 → 5
→ 6 → 7 → 8 → 9 → 10
9 10 9 7 パターン6. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
前に戻っていった場合 (移動回数を – とする)
総数 キャプチャ
(By Instagram.)
移動過程 移動回数
( → の数)
現在ページ 前ページ ドットの数 ドットパターン
10 5 → 4 -1 4 5 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
5 → 4 → 3 → 2 → 1 -4 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
6 → 5 -1 5 6 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
6 → 5 → 4 → 3 → 2 -4 2 3 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
6 → 5 → 4 → 3 → 2
→ 1
-5 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
7 → 6 -1 6 7 9 パターン9. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
7 → 6 → 5 → 4 → 3 -4 3 4 9 パターン9. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
7 → 6 → 5 → 4 → 3
→ 2
-5 2 3 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
7 → 6 → 5 → 4 → 3
→ 2 → 1
-6 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
8 → 7 -1 7 8 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
8 → 7 → 6 → 5 → 4 -4 4 5 9 パターン9. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
8 → 7 → 6 → 5 → 4
→ 3
-5 3 4 9 パターン9. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
8 → 7 → 6 → 5 → 4
→ 3 → 2
-6 2 3 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
8 → 7 → 6 → 5 → 4
→ 3 → 2 → 1
-7 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
9 → 8 -8 1 9 8 パターン8. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後の1つが少し小さいドット
9 → 8 → 7 → 6 → 5 -4 5 6 8 パターン8. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後の1つが少し小さいドット
9 → 8 → 7 → 6 → 5
→ 4
-5 4 5 9 パターン9. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
9 → 8 → 7 → 6 → 5
→ 4 → 3
-6 3 4 9 パターン9. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
9 → 8 → 7 → 6 → 5
→ 4 → 3 → 2
-7 2 3 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
9 → 8 → 7 → 6 → 5
→ 4 → 3 → 2 → 1
-8 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
10 → 9 -1 9 10 7 パターン6. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
10 → 9 → 8 → 7 → 6 -4 6 7 7 パターン6. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
10 → 9 → 8 → 7 → 6
→ 5
-5 5 6 8 パターン8. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後の1つが少し小さいドット
10 → 9 → 8 → 7 → 6
→ 5 → 4
-6 4 5 9 パターン9. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
10 → 9 → 8 → 7 → 6
→ 5 → 4 → 3
-7 3 4 9 パターン9. ・先頭の1つが微小のドット
・先頭から2つ目が少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
10 → 9 → 8 → 7 → 6
→ 5 → 4 → 3 → 2
-8 2 3 8 パターン7. ・先頭の1つが少し小さいドット
・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット
10 → 9 → 8 → 7 → 6
→ 5 → 4 → 3 → 2 → 1
-9 1 2 7 パターン4. ・通常のドット5つ
・最後から2つ目が少し小さいドット
・最後の1つが微小のドット

ここまででわかったこと(その1)

  • スライド対象オブジェクトが5個まではカレントが移動するのみ
  • 初期に表示されるドットの数はMaxで7個まで
  • 同じ方向(次へ, 前へ)への移動回数が(+-)5回以上になってくるとドットパターンが変わるケースが出てくる
  • 次へのドットは少し小さいドットと微小のドット、最大で2個表示される
  • 前へのドットは少し小さいドットと微小のドット、最大で2個表示される
  • 通常サイズのドットは最大で5個表示される
  • ドットパターンは以下に分けられる

ドットパターン

パターン1.

  • 通常のドットのみ並ぶ(最大5つまで)

パターン2.

  • 通常のドット5つ
  • 最後の1つが少し小さいドット

パターン3.

  • 先頭の1つが少し小さいドット
  • 通常のドット5つ

パターン4.

  • 通常のドット5つ
  • 最後から2つ目が少し小さいドット
  • 最後の1つが微小のドット

パターン5.

  • 先頭の1つが少し小さいドット
  • 通常のドット5つ
  • 最後の1つが少し小さいドット

パターン6.

  • 先頭の1つが微小のドット
  • 先頭から2つ目が少し小さいドット
  • 通常のドット5つ

パターン7.

  • 先頭の1つが少し小さいドット
  • 通常のドット5つ
  • 最後から2つ目が少し小さいドット
  • 最後の1つが微小のドット

パターン8.

  • 先頭の1つが微小のドット
  • 先頭から2つ目が少し小さいドット
  • 通常のドット5つ
  • 最後の1つが少し小さいドット

パターン9.

  • 先頭の1つが微小のドット
  • 先頭から2つ目が少し小さいドット
  • 通常のドット5つ
  • 最後から2つ目が少し小さいドット
  • 最後の1つが微小のドット

少し複雑なパターンで移動した場合

今までのパターンだと、ある程度次へ進んでから戻るを実施しただけの単純なパターンのみなので、以下のパターンでスライドを移動させてみます。
※ スライド対象オブジェクト数は 9 とします

  1. 1ページ目から8ページ目まで移動
  2. 8ページ目から2ページ目まで移動
  3. 2ページ目から9ページ目まで移動
  4. 9ページ目から5ページ目まで移動
  5. 5ページ目から9ページ目まで移動
  6. 9ページ目から1ページ目まで移動
  7. 1ページ目から8ページ目まで移動
  8. 8ページ目から7ページ目まで移動
  9. 7ページ目から9ページ目まで移動

1ページ目から8ページ目まで移動

現在ページ 1 2 3 4 5 6 7 8
ドットパターン
↓ カレントが移動するのみ
パターン4. パターン7. パターン9. パターン8.

8ページ目から2ページ目まで移動

現在ページ 8 7 6 5 4 3 2
ドットパターン
↓ カレントが移動するのみ
パターン8. パターン9. パターン7.

2ページ目から9ページ目まで移動

現在ページ 2 3 4 5 6 7 8 9
ドットパターン
↓ カレントが移動するのみ
パターン7. パターン9. パターン8. パターン6.

9ページ目から5ページ目まで移動

現在ページ 9 8 7 6 5
ドットパターン
↓ カレントが移動するのみ
パターン6.

5ページ目から9ページ目まで移動

現在ページ 5 6 7 8 9
ドットパターン
↓ カレントが移動するのみ
パターン6.

9ページ目から1ページ目まで移動

現在ページ 9 8 7 6 5 4 3 2 1
ドットパターン
↓ カレントが移動するのみ
パターン6. パターン8. パターン9. パターン7. パターン4.

1ページ目から8ページ目まで移動

現在ページ 1 2 3 4 5 6 7 8
ドットパターン
↓ カレントが移動するのみ
パターン4. パターン7. パターン9. パターン8.

8ページ目から7ページ目まで移動

現在ページ 8 7
ドットパターン
パターン8. パターン8.

7ページ目から9ページ目まで移動

現在ページ 7 8 9
ドットパターン
パターン8. パターン8. パターン6.

ここまででわかったこと(その2)

  • 同じ方向への移動回数が5回以上になったタイミングで進む方向を変えた場合、再度その方向(変えたほうへの方向)へ5回以上進まないとドットパターンは変わらない
    • 上にある通り1ページ目から8ページ目へ移動(次へ)したあとは、前へ5回(8ページ目から3ページ目まで)進まないとドットパターンは変化しない
  • ただし、進む方向を変えた場合でも、その後に再び進む方向を戻して進んでいった結果、もともと進んでいた方向の移動回数 + 再び進んだ方向への移動回数が5回以上の移動回数になればドットパターンが変わる
    • 1ページ目から8ページ目まで移動、8ページ目から7ページ目まで移動、7ページ目から9ページ目まで移動したときのパターンをみると明白
  • 次への移動回数と前への移動回数を保持しておく必要がある
  • 次への移動なのか前への移動なのかを判別するために現在のページと前にいたページを知っておく必要がある
  • 次への移動は
    • 現在のページ >= 前にいたページ でわかりそう
  • 前への移動は
    • 現在のページ < 前にいたページ でわかりそう
  • 次への移動が5回以上、前への移動が-5回以上のタイミングを取ることを考えると以下のようにやるのがよさそう
  • 次へ移動した場合は次への移動回数を取得して保持しておく
    • 前回保持しておいた次への移動回数に加えて保持する
    • 5回以上の回数は特に考えなくていいので5を超えたら5にまるめておく
    • ページが飛ばされることも考える(1 → 4ページ目)
    • となると、現在のページ - 前にいたページ が次への移動回数
  • 前へ移動した場合は前への移動回数を取得して保持しておく
    • 前回保持しておいた前への移動回数から減算して保持する
    • -5回以上の回数は特に考えなくていいので-5より小さくなれば-5にまるめておく
    • ページが飛ばされることも考える(4 → 1ページ目)
    • となると、前にいたページ - 現在のページ が前への移動回数
  • 移動回数が+5-5のときにドットパターンの変化を考えたいので
  • 次へ移動した場合、前への移動回数に次への移動回数をプラスする
    • その結果、前への移動回数が0以上になった場合0にまるめておく
  • 前へ移動した場合、次への移動回数から前への移動回数をマイナスする
    • その結果、次への移動回数が0以下になった場合0にまるめておく
  • 上記を考えると次への移動回数と前への移動回数の初期値(1ページ目での)は以下でよさそう
    ※ 1ページより前のページは無い && 前への移動回数は-5以下にしないことから
    • 次への移動回数初期値 … 0
    • 前への移動回数初期値 … -5

これらを加味して、もう一度移動回数を整理したのが以下になります。

移動回数の整理

1ページ目から8ページ目まで移動

現在ページ 1 2 3 4 5 6 7 8
次への移動回数 0 1 2 3 4 5 5 5
前への移動回数 -5 -4 -3 -2 -1 0 0 0
ドットパターンの変化 なし
(パターン4.)
なし
(パターン4.)
なし
(パターン4.)
なし
(パターン4.)
なし
(パターン4.)
あり
(パターン7.)
あり
(パターン9.)
あり
(パターン8.)

8ページ目から2ページ目まで移動

現在ページ 8 7 6 5 4 3 2
次への移動回数 5 4 3 2 1 0 0
前への移動回数 0 -1 -2 -3 -4 -5 -5
ドットパターンの変化 なし
(パターン8.)
なし
(パターン8.)
なし
(パターン8.)
なし
(パターン8.)
なし
(パターン8.)
あり
(パターン9.)
あり
(パターン7.)

2ページ目から9ページ目まで移動

現在ページ 2 3 4 5 6 7 8 9
次への移動回数 0 1 2 3 4 5 5 5
前への移動回数 -5 -4 -3 -2 -1 0 0 0
ドットパターンの変化 なし
(パターン7.)
なし
(パターン7.)
なし
(パターン7.)
なし
(パターン7.)
なし
(パターン7.)
あり
(パターン9.)
あり
(パターン8.)
あり
(パターン6.)

9ページ目から5ページ目まで移動

現在ページ 9 8 7 6 5
次への移動回数 5 4 3 2 1
前への移動回数 0 -1 -2 -3 -4
ドットパターンの変化 なし
(パターン6.)
なし
(パターン6.)
なし
(パターン6.)
なし
(パターン6.)
なし
(パターン6.)

5ページ目から9ページ目まで移動

現在ページ 5 6 7 8 9
次への移動回数 1 2 3 4 5
前への移動回数 -4 -3 -2 -1 0
ドットパターンの変化 なし
(パターン6.)
なし
(パターン6.)
なし
(パターン6.)
なし
(パターン6.)
なし(パターン6.)
※ ドットパターン切り替えの対象となるが変化はしない

9ページ目から1ページ目まで移動

現在ページ 9 8 7 6 5 4 3 2 1
次への移動回数 5 4 3 2 1 0 0 0 0
前への移動回数 0 -1 -2 -3 -4 -5 -5 -5 -5
ドットパターンの変化 なし
(パターン6.)
なし
(パターン6.)
なし
(パターン6.)
なし
(パターン6.)
なし
(パターン6.)
あり
(パターン8.)
あり
(パターン9.)
あり
(パターン7.)
あり
(パターン4.)

1ページ目から8ページ目まで移動

現在ページ 1 2 3 4 5 6 7 8
次への移動回数 0 1 2 3 4 5 5 5
前への移動回数 -5 -4 -3 -2 -1 0 0 0
ドットパターンの変化 なし
(パターン4.)
なし
(パターン4.)
なし
(パターン4.)
なし
(パターン4.)
なし
(パターン4.)
あり
(パターン7.)
あり
(パターン9.)
あり
(パターン8.)

8ページ目から7ページ目まで移動

現在ページ 8 7
次への移動回数 5 4
前への移動回数 0 -1
ドットパターンの変化 なし
(パターン8.)
なし
(パターン8.)

7ページ目から9ページ目まで移動

現在ページ 7 8 9
次への移動回数 4 5 5
前への移動回数 -1 0 0
ドットパターンの変化 なし
(パターン8.)
なし(パターン8.)
※ ドットパターン切り替えの対象となるが変化はしない
あり
(パターン6.)

なんか、なんとなくいけそうな気がする..?

わかったこと

これまでに書いたもろもろを考慮すると、以下のパターンも見えてきたような気がします。

初期表示

  • 総数 <= 5
    • そもそも総数が5ページ以下の場合、ドットパターンはパターン1に収まる
    • よって、パターン1の描画のみ行えばいいので考慮しない
  • 総数 - 5 == 1の場合
    • 後ろに1つドットを追加
    • ドットパターンはパターン2の状態
  • 総数 - 5 >= 2の場合
    • 後ろに2つドットを追加
    • ドットパターンはパターン4の状態

(最大2つまで描画される)前へのドットの描画条件

次へ進んでいて

  • ドットパターンの変化なし、または、現在ページ - 1 < 5の場合
    • 前にドットなし
  • 現在ページ - 1 == 5の場合
    • 前に1つドットを追加
    • ドットパターンはパターン3の状態
  • 現在ページ - 1 >= 6の場合
    • 前に2つドットを追加
    • ドットパターンはパターン6の状態

前へ戻っていて

  • ドットパターンの変化なし、または、現在ページ == 1の場合
    • 前にドットなし
  • 現在ページ == 2の場合
    • 前に1つドットを追加
  • 現在ページ >= 3の場合
    • 前に2つドットを追加

(最大2つまで描画される)次へのドットの描画条件

  1. 前へのページドットの中で一番大きいページの数を取得
    前へのページドットの各ページが 2, 3 となっていれば3が対象
    1. で取得した値と5(通常ドット最大表示数)を足す
  2. ドットの表示終了ページ※後述 から2.で取得した値を引く

これで求めた値が次へのドットの描画数となります。

例えば、総数が10で9ページ目まで移動した場合は1となります。
※ 上の式に当てはめると、10 - (4 + 5) = 1となります
4は前へのページドットの中で一番大きいページの数です
10はドットの表示終了ページ※後述 です

ドットの表示開始ページ

  • (現在ページ + 1) - 7 で求める
    • 求めた結果、1以下になれば、1でまるめる
    • 7は、2(前へのドット最大表示数) + 5(通常ドット最大表示数)

例えば、総数が10で10ページ目まで移動した場合、ドットのパターンはパターン6.で、一番先頭に描画される微小ドットのページは4を指します。
この4が開始ページとなります。
※ 上の式に当てはめると、(10 + 1) - 7 = 4となります

前に移動している場合のドットの表示開始ページ

  • 現在ページ - 前へのドットの表示数 で求める

例えば、総数が10で10ページ目まで移動 -> 5ページ目まで戻った場合、ドットのパターンはパターン8.で、一番先頭に描画される微小ドットのページは3を指します。
この3が開始ページとなります。
※ 上の式に当てはめると、5 - 2 = 3となります

ドットの表示終了ページ

  1. 前へのページドットの中で一番大きいページの数を取得
    前へのページドットの各ページが 2, 3 となっていれば3が対象
    1. で取得した値と7を足す
      7は、2(前へのドット最大表示数) + 5(通常ドット最大表示数)
  2. 2.で求めた値 > 総数 であれば総数がドットの終了ページ
  3. 2.で求めた値 <= 総数 であれば2.で求めた値がドットの終了ページ

例えば、総数が10で7ページ目まで移動した場合、ドットのパターンはパターン9.で、一番最後に描画される微小ドットのページは9を指します。
この9が終了ページとなります。
※ 上の式に当てはめると、2(前へのページドットの中で一番大きいページの数) + 7 = 9となります

なんとなくルールはよめてきたので、あとは実装するのみです。

実装の前に

実装の前に、上記の動きが再現できそうか確認をしてみます。
まず、ページネーションのカスタムをするには

これらを活用すれば良さそうな気がします。

お試し実装

試しに、5枚画像を用意して、偶数のページ(2枚目と4枚目)は無視する実装を行ってみます。
※ 画像はこちらです

<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css">
  <style>
  * {
    margin: 0;
    padding: 0;
  }

  .container {
    display: flex;
    height: 100vh;
    width: 100vw;
    background-color: #202020;
  }

  .my-swiper {
    width: 100%;
    max-width: 960px;
    height: 250px;
    align-self: center;
    padding-bottom: 36px;
  }

  .slide {
    width: 100%;
    height: 100%;
    background-color: #ffffff;
  }

  .slide-image {
    width: 100%;
    height: 100%;
    object-fit: contain;
  }

  .swiper-pagination-bullet {
    margin-right: 10px;
  }

  .swiper-pagination-bullet:hover {
    cursor: pointer;
  }
  </style>
</head>
<body>
  <div class="container">
    <div class="swiper my-swiper">
      <div class="swiper-wrapper">
        <div class="swiper-slide">
          <div class="slide">
            <img class="slide-image" src="./img/example_1.png" alt="example_1">
          </div>
        </div>
        <div class="swiper-slide">
          <div class="slide">
            <img class="slide-image" src="./img/example_2.png" alt="example_2">
          </div>
        </div>
        <div class="swiper-slide">
          <div class="slide">
            <img class="slide-image" src="./img/example_3.png" alt="example_3">
          </div>
        </div>
        <div class="swiper-slide">
          <div class="slide">
            <img class="slide-image" src="./img/example_4.png" alt="example_4">
          </div>
        </div>
        <div class="swiper-slide">
          <div class="slide">
            <img class="slide-image" src="./img/example_5.png" alt="example_5">
          </div>
        </div>
      </div>
      <div class="swiper-pagination"></div>
    </div>
  </div>
<script src="https://unpkg.com/swiper/swiper-bundle.min.js"></script>
<script>
  // Make Swiper.
  new Swiper('.my-swiper', {
    pagination: {
      el: '.swiper-pagination',
      clickable: true,
      type: 'custom',
      renderCustom: function (swiper, current, total) {
        let html = '';
        let className = '';
        swiper.slides.forEach((_, index) => {
          if (index % 2 !== 0) { // 偶数ページであればdisplay:noneで隠す
            html += '<span style="display:none;"></span>';
            return;
          }
          if (index + 1 === current) {
            className = 'swiper-pagination-bullet swiper-pagination-bullet-active'; // カレントページ
          } else {
            className = 'swiper-pagination-bullet';
          }
          html += `<span class="${className}"></span>`;
        });
        return html;
      },
    }
  });
</script>
</body>

一番左のドット(ページネーション)クリックで1枚目を表示、真ん中のドットクリックで3枚目を表示、一番右のドットクリックで5枚目が表示されるようになりました。
このように、無視したいページはdisplay:noneで隠してあげて、表示したいページは.swiper-pagination-bulletをつけて返してあげると良さそうです。
(なお、この表現だと画像のスワイプをしてしまうと偶数のページも見れてしまいますので、そこはあしからず)

うん、なんとなくこのへんをうまいことやれば出来そうですね。
あとはひたすら実装するのみです。
※ これ以上はソースを見ていただければと思います

おわりに

なにかのUI実装を真似ようと思ったら、パターンを地味に丁寧に1つずつ洗い出してみると(正確では無いかもしれませんが)アルゴリズムが見えてくる気がしたこの頃でした。
※ ただし相当疲れるぞ!

作成者: shimabox

Web系のプログラマをやっています。 なるべく楽しく生きていきたい。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください