巨大なテーブル要素を素早く描画する方法
私は普段BIツールのWebUIを開発していますが、BIツールというのは大量のデータをビジュアライズする必要があるので、何も考えずに描画するとすぐブラウザが固まってしまいます。
この記事では、そんなBIツールの中で数十万セルのテーブルをサクサク表示するために行っている工夫について説明します。
まずはベタに実装するとどうなるか
こちらがBIツールで表示している表です。固定ヘッダーの表になっていて、白の値セルのあたりをスクロールしてもヘッダーが隠れないようにしてあります。
このスクロールの実装のために下のようにdivで分割しています。
この中にそれぞれtable要素を配置しており、右下の値セルのスクロールを行うと、上左のヘッダー部も連動してスクロールするようになっています。
さて、これを特に何も考えずにベタに実装し、縦1000セル、横250セルくらいのテーブルを表示させると、まあFirefoxとChromeは2秒程度で出してくれますが、スクロールはまともにできませんし、IEだと初期表示だけでも9秒程度掛かります。
BIツールのダッシュボードに表示する表はこれ一枚ではないので、ページをすべて表示するのに十秒以上掛かるようなことになってしまいます。
早くする
本来ならちゃんと測ってからとなりますが、まあ今回遅いのは追加するノード数が大きすぎなのは自明なのでサクッとノード数を減らします。
この図は先ほどのdivの構成ですが、ヘッダーと値セルのtableは実態は数十万ありますが、実際に画面描画する時に必要なのは、この見えている範囲の数えられる程度の要素です。
不要なものを描画しなければサクッと表示できるサイズになります。
というわけで見えてる範囲で切り出して描画するように変えます。
これで2秒程度掛かってた描画が100msくらいまで早くなりました。
スクロール
さて、次はスクロールです。見えている範囲に切り抜いて表示しているので、スクロールする際には当然移動した先の要素に書き換えてやらねばいけません。
ブラウザのスクロールは極力そのまま使いたいため、tableの外側に真の表のサイズのdivを配置し、スクロール量に合わせて描画位置を移動させながらテーブルを作り直します。
さすがに60FPSでなめらかスクロールとはいきませんが、まあ実用上問題ない程度のスピードは出ます。
このような感じで巨大なtableをサクサク表示させています。
終わりに
ちょっとしたリスト表示のためにtableを使っている時でも気を抜くと要素数が大きくなり表示やスクロールが途端に大きくなってしまいます。
そんな時、ページングできればもっと簡単ですが、それが難しい時にはこのように描画ノードを絞って表示すると高速に表示できるようになります。