Nullable<T>

仮想スクロールの仕組みと魅力

February 18, 2019

仮想スクロールの仕組み

必要な要素と動きに着目する。

要素

parts.png

  1. 見える範囲を指定するためのDiv
  2. スクロールする高さを指定するDiv
  3. ListItemを置くUnorderdList
  4. ListItem

また、以下の要素をあらかじめ指定する。

  1. 見える範囲に表示する4のListItemの個数
  2. 4のListItemの総数
  3. 4のListItemの高さ

スクロールした時の動き

scrolling.png

このようなイメージ。 要は、スクロールする時に2のDivが上に移動し、スクロールした量に応じてインデックスを割り出して、インデックス x リストアイテムの個数分だけ3のUnorderedListが下に移動する

インデックスに関しては、 表示すべき最初のリストアイテムの番号的なもので、以下のような感じで求める。

// スクロール量
const scrollPosition = e.currentTarget.scrollTop;
 
// スクロール量 / ListItemの高さ で インデックスを求める
const index = Math.floor(scrollPosition / itemHeight);

細かいところもう少しあるけど、本質的ではない(魅力を知らせたい)ため、割愛。

仮想スクロールの魅力

通常のスクロールと比べると、やや難易度が上がる仮想スクロールだが、レンダリング速度が段違い。

計測

計測パターンとして

  • 仮想スクロール - リストアイテム100, 1000, 10000個
  • 通常スクロール - リストアイテム100, 1000, 10000個

の6パターンを試す。

計測結果

perform.png

種別と個数 100 1000 10000
仮想スクロール 2ms 3ms 3ms
通常スクロール 10ms 80ms 850ms

超超超ざっくりこんな感じ。 結果からは下記の2点がわかる。

  1. 仮想スクロールの場合は、レンダリング時間にあまり変化がない
  2. 通常スクロールの場合は、レンダリング時間がリストアイテムの個数だけ増えていっている(1倍,10倍,100倍)

圧倒的に仮想スクロールは早い。これこそが魅力。

無限スクロールとの違い

レンダリング速度の改善という意味では、近いところに無限スクロールがある。 ちなみに、無限スクロールとは、ツイッターのタイムラインのように適宜読み込んでいくもの。

大きく違うところは、総数がわかるかどうかというあたり。 そう考えるとそれぞれの用途は

無限スクロール 仮想スクロール
俯瞰して見る必要はない 俯瞰して見る必要がある

こう分かれる。

だから、仮想スクロールを選択する場面としては、フォームなどであらかじめ用意しておいた選択肢から選んでもらう時などだ。

おわりに

実際は同じような感じで色々と実装方法ある。

通常スクロールと仮想スクロールの汚いサンプルコード(React)はこちら。

通常スクロールのサンプルコード / 仮想スクロールのサンプルコード

ちなみに、Reactであれば、 react-virtualizedreact-tiny-virtual-list のようなモジュールで超簡単に実装できる。


Written by Ryo @neer_chan

© 2018-2020 Nullable<T>