始めに
カルーセルのライブラリといえばslick.jsやSwiperなどがあると思いますが、どちらもオプションが多く、バグにもよくハマっていました。おまけにファイルサイズも大きいので、簡単なことやるだけに入れる必要があるのかなと思うことがありました。
そこでカルーセルを自作してみたのですが、どんな感じで実装したかを記事にまとめてみました。
実装方法
各項目の表示と位置について
要素の移動はtransformでまとめて移動する方法を取りますが、移動量は可能な限りシンプルになるようにしました。
親要素はwhite-space: nowrap
で改行されないようにし、子要素でdisplay: inline-block
で横に並べていきます。この時marginはつけないようにします。marginをつけずぴったりくっつけることで1つ移動するたびにtranslate3d(-100%, 0, 0)
で遷移できるようになります。
スペースを入れたい場合はpaddingを入れて、その中で新たに要素を入れることで実現しています。
※一番上の親要素はあえてblockのままにすると項目一つ分のサイズにできるので中央ぞろえがやりやすくなります。
※translateXでなくtranslate3dにしている理由はGPUレンダリングにさせるためです
スワイプ中の処理
上の方法で各項目の場所に移動するのはできるようになりました。
次にスワイプの処理ですが、これは単純に開始位置と移動中の位置を取得して、その差分だけずらしてあげればいいです。
上の説明と合わせると%とpxの指定になりますが、transform: translate3d(-100%, 0, 0) translate3d(-30px, 0, 0)
のように重ねてtranslateできます。
後は離したときにその差分に応じて前か後ろに移動したらOKです。
注意として、話した後の移動はCSSアニメーションでいいですが、スワイプ中の移動でそれがあるともたついているように見えるので、スワイプ中はCSSアニメーションはOFFにする必要があります。
図ではマウスを例にしていますが、タッチの場合も同じことをすればいいです。
無限カルーセルの実装
以上が通常のカルーセルの実装でしたが、無限カルーセルをする場合はどうするかについても紹介したいと思います。
まず表示は前後にコピーの要素を配置します。これで初期位置でも前に最後の要素が見えるようになります。
次に遷移先の場所の調整ですが、通常のカルーセルでは0~要素数になるようにスワイプを終えたときに調整してましたが、無限スクロールではアニメーション中まではその調整は行わないようにします。なのでアニメーション中はコピー要素が中心に来るときもあります。
このまま進めたらいつかコピー要素もない場所まで移動できてしまうので、アニメーションが終わったタイミングで一気に逆サイドの本体要素の場所まで移動します。この移動はアニメーションをOFFにしていると気づかないので問題ないです。
終わりに
以上がカルーセルを実装する方法でした。コードを書こうとすると結構ごちゃごちゃして分かりづらかったのであえて図だけで説明しました。
詳しい実装はCodePenに書きましたので、そちらを見ていただけると幸いです。