データグリッドの仕組みとその理由

グリッド( datagrid )またはテーブルの形式で何かを表示する作業が非常に一般的であることは誰にとっても秘密ではないと思います。 さらに、大量のデータがある場合、結果を(HTMLで)表示することは非常に重要なタスクになります。これは通常、ページネーションによって解決されます。





ユーザーに大量のデータを表示する他の方法を見てみましょう。さらに、結果をフィルタリングして検索し、さらに遅くなりすぎないようにすることが望ましいです:)。



通常、「モデル」ではなく「ビュー」にブレーキをかけます



原則として、結果をHTMLテーブルの形式で表示すると、表示パフォーマンスが低下します。結果全体が一度にレンダリングされます。 実践が示すように、Mozilla FirefoxおよびInternet Explorerでは、大きなテーブルの最初のレンダリングに費やされる時間が非常に長いため、この問題を何らかの方法で解決したいと思います。



通常、この問題はページネーションと一度にテーブルのごく一部のみをレンダリングすることで回避されますが、ユーザーはページを手動で切り替える必要があり、あまり便利ではありません。 ページネーションを使用する場合、データサンプリングの速度はレンダリングよりもはるかに高速であり、この事実はグリッドの作成に使用されます。



最も一般的なケースは、固定された行の高さです


表示する行の高さが固定されている場合、 SlickGridなどの既製のソリューションが多数あり、それらはすべて、結果のテーブルの高さを事前に計算し、ユーザーがスクロールするときに必要に応じて行を描画できるという非常に単純なアイデアを使用します適切なエリアに。



同様のグリッドは、Cocoa、WPF、Swingなど、ほとんどすべてのGUIライブラリとフレームワークに存在します。 いくつかの実装では、スクロールは1行ずつしか許可されません(Windowsのほとんどのソリューション)。他の実装では、行の中央にスクロールできます(Cocoa)





可能性としては、既存のソリューションがこれをかなりうまくやっているということです。



それほど一般的ではなく、より複雑な場合は、行の高さが可変です。


ここで、より興味深いオプションを考えてみましょう-行の高さは可変で、各行の高さはレンダリングされた後にしかわからないとしましょう。 場合によっては、レンダリングしなくても高さを知ることができますが、いずれにしても、セルの高さが変化する可能性があるという事実は重要です。 人生がラズベリーに見えないように、テーブル内の列の幅も変更できるため、高さをキャッシュすることを禁止するという条件も設定します。



ここには2つのアプローチがあり、1つはiWorkのNumbers.appで使用され、もう1つはOpenOffice.org CalcとMicrosoft Excelで使用されます。 両方を見て、利点と欠点を分析しましょう。



簡単な方法。 全表レンダリング


全表レンダリングでは、3つのことを行います。



1.テーブル全体をレンダリングし、その高さを決定し、ユーザーに実際のスクロールを描画します

2.常に、編集された行の高さを数え、スクロールの状態を更新します

3.列の幅が変更された場合、すべての行の高さを再計算し、スクロールの状態を更新します



Numbers.appはこのパスを自身で選択し、ブラウザで通常のHTMLテーブルをレンダリングするときに同じパスを使用します(ブラウザもテーブルをコンテナの幅に合わせようとするため、いくつかの追加があります)。



このアプローチが悪い理由は、ブラウザーまたはNumbers.appでかなり大きなテーブル(10列の10,000レコードなど)を開くことで簡単に理解できると思います。 コンテンツを操作するとき、およびテーブルをロードするとき、すべてがひどくゆっくりとロードされて動作し、アプリケーションがハングします。



このアプローチは、コンテンツごとのスクロールが非常に迅速に(すべてのコンテンツが既にレンダリングされているため)スムーズに行われ、ユーザーに表示されるスクロールの高さが、表示されるコンテンツの実際の高さに対応するという点で優れています。



ご想像のとおり、別の方法があります。



トリッキーな方法。 偽のスクロールで可視部分をレンダリングする


テーブルに多くのデータがある場合、ユーザーは、スクロールの高さがすべてのセルの高さの合計にわずかに対応しないという事実に気付かない可能性があります。 これは何を意味し、どのように使用できますか? そしてそれは非常に簡単です:



スクロールの高さを確認するために何もレンダリングしません-固定行の高さの場合と同様に、この単純な式を使用して計算します:



SCROLL_HEIGHT = N * ROW_HEIGHT


ここで、SCROLL_HEIGHTはスクロールの高さ(つまり、スクロールでスクロールする「コンテンツ」の高さ)、Nは行数、ROW_HEIGHTは1行の高さ(たとえば30px)です。



論理的な問題が発生します-スクロール位置(SCROLL_TOP)の指定された値で描画すべき内容を理解するにはどうすればよいのですか?それはコンテンツの実際の高さに対応していないからです? 答えは、高さの計算に使用した式から得られます。



CURRENT_POSITION = [SCROLL_TOP / ROW_HEIGHT]


ここで、[...]は番号の整数部分を意味し、CURRENT_POSITIONは番号付けが最初からの場合、現在表示されている最初の行のインデックスです。



この番号で何をすべきでしょうか? CURRENT_POSITIONで始まるすべての可視線を描画する必要があります。 つまり、CURRENT_POSITIONで始まり、セルの境界を越えるまで、すべての行を1行ずつ描画します。



このスクロール方法は、 ごとのスクロールに対応します 。つまり、常に中央からではなく特定の行から描画するため、行の中央までスクロールすることはできません。 これは、線の高さが、描画する領域の高さを超える場合、線の一部のみが表示され、残りのコンテンツが表示されないことを意味します ! この場合にスクロールしようとすると、すぐに次の行に移動し、前のセルはスコープから完全に非表示になります。 信じられない場合は、Microsoft Excelでこの動作を確認できます:)。



ユーザーがスクロールを放した後、最初の式に従って、スクロールを調整できます。



SCROLL_TOP = CURRENT_POSITION * ROW_HEIGHT


実際、現在の行番号の決定はさまざまな方法で行うことができますが、これはスクロールの不要な「けいれん」を引き起こさない方法の1つにすぎません。



Microsoft ExcelとOpenOffice.org Calcでは、行だけでなく列にもまったく同じレンダリングメカニズムが使用されます。この場合、行ごとにレンダリングは行われませんが、より複雑なアルゴリズムに従って行われます。



初心者向けガイド


私は自分のファイルマネージャーを含むいくつかのプロジェクトで、これらのレンダリングメカニズムを自分で使用しました。 いずれにせよ、誰かが上記のアルゴリズムを自分で実装したい場合、実践からのいくつかのヒントがあります:



1.仮想スクロールを使用してグリッドを描画する最も簡単な方法は、絶対位置の<div>を作成することです。これは、jQueryのoffset()メソッドを使用して簡単に決定できるコンテナの上部に表示されます。

2. <div>自体を2にすることができます。1つはコンテンツを使用し、もう1つはスクロールのみを使用して、ブラウザがコンテンツを使用して<div>をスクロールしようとしないようにします。 また、position:fixedを使用して試すこともできますが、IE 7では奇妙に動作します

3.ブラウザはスクロールを特別に制御しないため、スクロールの位置はまったく揃えないことが最適です。

4. IE 7の最大要素の高さは約100万ピクセルです。したがって、仮想線の高さを30ピクセルにすると、約30,000行の制限があります。 これに対処するには、ブラウザがIEの場合、エントリ数を増やして仮想行の高さを減らすことができます

5.マウスホイールでスクロールするときに行をスクロールするには、GeckoベースのブラウザーでDOMMouseScrollイベントを処理し、残りすべてでマウスホイールを処理できます。

6.完全に表示されている領域を再描画するよりもスマートな再描画を行う場合(つまり、少数の行にスクロールするときに動的に削除して新しい行を追加するなど)、結果について教えてください:)



グリッドをまだ実装している場合は、たとえばCocoaのグリッドAPIのドキュメントを参照してください。これにより、スケーラブルなソリューションを作成する方法を理解しやすくなります。



私は自分の決定を投稿したくありません。すべてが急いで、特定のタスクのために書かれたので、あなたの誰もがふさわしくないでしょう。 最後まで読んでくれてありがとう:))



All Articles