HTML
JavaScript
Web

仮想スクロールのすヽめ

平日の早朝に道玄坂を下るアベックに破滅と滅亡を。どうも、@neer_chanです。

皆さん、仮想スクロールしてますか?


概要


  • 仮想スクロールとは

  • 仮想スクロールの仕組み

  • 仮想スクロールの魅力

前提として、縦スクロールの話をします。


仮想スクロールとは

ezgif.com-video-to-gif.gif

GIFの通り、見えている範囲(+α)のみレンダリングするもの。

要は、ロケット鉛筆みたいなものです。(絶対に違う)


仮想スクロールの仕組み


イカれたメンバーを紹介するぜ!

parts.png


  1. 見える範囲を指定するためのDiv

  2. スクロールする高さを指定するDiv

  3. ListItemを置くUnorderdList

  4. いつかの、いくつかのきみとListItem

以上の4つが登場するメンバーだ!

ちなみに、通常のスクロールの場合は2の役割を3が行う感じになります。

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


  1. 見える範囲に表示する4のListItemの個数(あるいは1のDivの高さとかでも大丈夫)

  2. 4のListItemの総数

  3. 4のListItemの高さ


スクロールした時の動き

scrolling.png

このようなイメージです。

要は、スクロールする時に2のDivが上に移動し、スクロールした量に応じてインデックスを割り出して、インデックス x リストアイテムの個数分(実際はもうちょっと少ない)だけ3のULが下に移動します

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

// スクロール量

const scrollPosition = e.currentTarget.scrollTop;

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

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


仮想スクロールの魅力

さて、本題です!

通常のスクロールと比べると、やや難易度が上がる仮想スクロールについて、どのような魅力があるのでしょうか。

それはズバリ、レンダリング速度です。


計測する

計測パターンとして


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

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

の6パターンを試します。


計測結果

3分クッキングの「ここで昨日あらかじめ仕込んでおいた〜...」みたいなノリですぐ結果見ていきましょう。

 はいドン!

perform.png

種別と個数
100
1000
10000

仮想スクロール
2ms
3ms
3ms

通常スクロール
10ms
80ms
850ms

超超超ざっくりこんな感じですね

どうでしょうか、結果からは下記の2点がわかると思います。


  1. 仮想スクロールの場合は、レンダリング時間にあまり変化がない

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

圧倒的に仮想スクロールは早いですね! 

これこそが仮想スクロールの魅力です!


無限スクロールとの違い

レンダリング速度の改善という意味では、近いところに無限スクロールがあります。

無限スクロールとは、ツイッターのタイムラインのように適宜読み込んでいくものですね。

大きく違うところは、総数がわかるかどうかというあたりです。

そう考えるとそれぞれの用途は

無限スクロール
仮想スクロール

俯瞰して見る必要はない
俯瞰して見る必要がある

こう分かれます。

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


おわりに

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

Reactであれば、 react-virtualizedreact-tiny-virtual-list のようなモジュールで超簡単に実装できるので、早速実装しましょう!


弊社ではWebエンジニアを募集してます。(小声)

https://www.wantedly.com/projects/115932