LoginSignup
3
1

More than 1 year has passed since last update.

バーチャルカルーセルを自作する

Posted at

始めに

以前カルーセルを自作する方法について記事をまとめましたが、項目数が多くなったときに動作が重くなってしまう問題がありました。
そこで今回は見えている項目だけ出すバーチャルカルーセルの自作アイデアをまとめたいと思います。また、最近はVue3が使えるようになったのでそちらの書き方で作りました。

実装方法

各項目の表示と位置について

今回はposition: absoluteで1つ1つに対して位置を指定するようにします。absoluteではtop: 50%; left: 50%も加えて、いわゆる中央配置を全ての要素に設定します。その後、通常はtransform3d(-50%, -50%, 0)ですが、前後で100%分ずつずらして横に並ぶようにします。要素間のmarginは前回と同じようにpaddingを入れて対応します。
これによって最低5枚分表示するだけで済むようになります。この5枚に対してidxを中心とした前後2枚分の情報をslotで提供して表示させればOKです。もしindex値がマイナスや配列数を超えて中身がない場合は単純に非表示にすれば良いです。

カルーセルのコピー.jpeg

スワイプ中の処理

こちらは前回と同じように開始位置と移動中の位置を取得して、その差分だけずらすようにします。transform: translate3d(-100%, 0, 0) translate3d(-30px, 0, 0)のように%とpx指定を重ねることや、スワイプ中はアニメーションを切っておくことも同じです。

https___qiita-image-store.s3.ap-northeast-1.amazonaws.com_0_187768_7e7890a3-1930-bcc3-211a-d04b0cf3354a.jpeg

ただ注意として、ポジションの移動はいきなり設定するのではなく、一旦どっちに移動したかを変数で持っておく必要があります。アニメーション中はこの変数を元に表示位置だけ移動し、アニメーションが終わったら実際のidxも変更します。

カルーセルのコピー2.jpeg

ループの実装

ループは今回のやり方だと非常に簡単で、通常は要素がなかったら非表示ですが、こちらは1周回って表示される要素を出してあげるだけです。どっちでも対応できるようにgetItemメソッド経由にすると扱いやすいです。

const getItem = (index) => {
  // ループの場合
  if (props.loop) {
    const idx = (index + props.items.length) % props.items.length;
    return props.items[idx];
  }
  // 通常の場合はそのまま返す
  return props.items[index];
}

終わりに

以上がバーチャルカルーセルを実装する方法でした。absoluteで配置するやり方は以前も作ったことはありましたが、SlickやSwiperのライブラリを見ていると1つの大きなラッパーでまとめて全体を移動しているものが多かったのでそちらの実装方法を紹介していました。ただ要素数が多くなってきたときに最低限の枠を使い回す実装になるとabsoluteで作った方がやりやすいなと思って今回そのやり方を紹介しました。要素数も限定されるのでこちらの方が使い勝手良さそうだなと個人的には感じています。
サンプルコードはCodePenに書きましたので、詳細の実装を見たい方はこちらの方をご参照ください。

See the Pen カルーセル by wintyo (@wintyo1024) on CodePen.

3
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1