スコット・マレイ
コード・アーティスト

Tutorials > D3 > データのバインディング

データのバインディング

最終更新日 2012年12月30日(原文)  2013年03月25日(翻訳 / h.sakai

この章ではバインディング(結合)の仕組みと、データをバインドする(結合する)理由について説明します。

データ視覚化とは、データをビジュアルにマッピングする(対応付ける)過程のことです。データが入力であり、ビジュアルのプロパティ(属性)が出力となります。例えば数字が大きくなるほど棒を高くしたり、データがあるカテゴリに属する場合に明るい色を用いたりすることです。マッピングのルールを決めるのは自分自身です。

データの入力値と DOM 中の要素とのバインドに D3 を用います。バインドとは、データを特定の要素に結び付けることです。バインドによって、マッピングルールを適用するときに元の値が参照できるようになるのです。このバインド処理が無ければ、空っぽの、マッピングもされてない DOM 要素の山が意味もなく出来上がるだけです。

バインドに必要なもの

データを DOM にバインドするためには、 D3 の selection.data() メソッドを用います。しかしデータをバインドする前に、ふたつのものを正しく準備しておく必要があります。

  1. データ自体
  2. DOM 要素のセレクション

順番に見ていきましょう。

データ

D3 は様々な種類のデータの扱いに長けており、実際上、数値配列、文字配列、オブジェクト(それ自体がほかの配列、キーと値のペアを含んだもの)配列等、あらゆる種類の配列を受け取ることができます。JSON(と GeoJSON)の扱いもスマートで、さらにはCSV ファイルを読み込む組込メソッドも備えています。

しかしここでは分かりやすさ優先で、いささか退屈ですが、単純な数値配列から始めましょう。次の配列がこれから使うサンプルデータセットになります。

var dataset = [ 5, 10, 15, 20, 25 ];

セレクションの作成

まず最初に、セレクト対象を決める必要があります。つまり、データを結びつける対象をどの要素にするのかということです。ここでも極力話を単純化し、仮にデータセットの各値ごとに新しいパラグラフを生成したいとしましょう。こんなコードが浮かんだでしょうか?

d3.select("body").selectAll("p")

はい、正解です。しかしこのコードには落とし穴が潜んでいます。このコードの時点では、セレクト対象のパラグラフ要素 p は、まだ存在していない、ということです。実はこの点こそ D3 で多くの入門者が悩むところなのです。どうやってまだ存在していない要素がセレクトできるのでしょうか?ここの理屈はちょっと難しいので、がんばって理解するようにしてください。

謎を解く鍵は enter() にあります。D3 の最もミステリアスなメソッドです。説明は後回しにして、これが目的のコードになります。

d3.select("body").selectAll("p")
   .data(dataset)
   .enter()
   .append("p")
   .text("新しいパラグラフ!");

このコードのデモ画面をご覧ください。5つの新しい、同一内容のパラグラフが表示されていると思います。表示される仕組みは次の通りです。

d3.select("body") ? DOM の中から body を見つけ、その参照をチェインの次のステップに渡します。

.selectAll("p") ? DOM 要素のすべてのパラグラフ要素を選択します。ここでは該当する要素が存在しないため、メソッドは空のセレクションを返します。この空のセレクションは、すぐ後に作られるパラグラフ要素を表したものだと理解してください。

.data(dataset) ? データの値の個数を数え、解析します。データセットには 5 つの値が含まれているので、ここを通過するすべてのメソッドは、それぞれ値ごとに、合計 5 回繰り返されます。

.enter() ? データにバインドされた要素を新規に生成するためには enter() が必要です。このメソッドは最初に DOM を調べ、次に受け渡されたデータを調べます。もし該当する DOM 要素の数よりデータの値の個数が多い場合は、enter()新規にプレースホルダ(※)要素を生成し、そのプレースホルダへの参照をチェインの次のステップに渡します。次のステップでは、その参照に対して作業するわけです。(※プレースホルダ:最終的な値が決まるまでの間、仮に確保しておくその値の置き場所)

.append("p") ? enter() が生成したプレースホルダセレクションを受け取り、ここで(!)DOM に p 要素を挿入します。そして生成した要素の参照をチェインの次のステップに渡します。

.text("新しいパラグラフ!") ? 新しく生成された p 要素の参照を受け取り、テキストを代入します。

バインディング完了

以上です!データは読み込まれ、解析され、DOM に生成した新しい p 要素にバインドされました。納得できませんか?もう一度デモページ に戻って WEB インスペクタを開いてみましょう(訳注:WEB インスペクタのバージョン・設定によっては、下記のサンプル画面とレイアウト・デザイン、表示メッセージが異なる場合があります)。

Web inspector

OK、5 つのパラグラフが表示されてます。しかしデータはどこに行ったのでしょう?Console をクリックして次の JavaScript/D3 コードを打ち込み、リターンキーを押してください。

console.log(d3.selectAll("p"))

JS console

配列が表示されました!灰色小三角の表示ボタンをクリックして詳細を表示させましょう。

JS console

0 から 4 までの 5 つの HTMLParagraphElement が表示されていますね?(訳注:WEB インスペクタのバージョン・設定によっては HTMLParagraphElement ではなく単に p と表示されます)。最初の(0 番目の)表示ボタンをクリックしてください。

JS console

お分かりでしょうか?画像はコンソール画面の最初の部分だけですが、この中にデータが表示されています。

JS console highlight

データの最初の値 5 が最初のパラグラフの __data__ 属性に表示されています。他のパラグラフ要素もクリックしてください。それぞれの __data__ の値が、最初にデータセットで定義した通り、10、15、20、25 となっているはずです。

つまり、D3 がデータを要素にバインドした時、そのデータは DOM 中に記録されるのではなく、メモリ上でその要素の __data__属性として記録されているのです。データがちゃんと要素にバインドされたかどうかは、こうやってコンソール画面から確認できます。

以上でデータの準備は完了です。いよいよデータを活用していく番です。

次章はデータの使い方

インタラクティブ・データ・ヴィジュアライゼーション このチュートリアルの書籍版の翻訳がオライリー・ジャパンより発売されました。タイトルは『インタラクティブ・データビジュアライゼーション ―D3.jsによるデータの可視化』です(画像をクリックするとアマゾンに飛びます)。

このチュートリアルを大幅に拡充し、3倍近い内容となっています。JavaScriptを中心に基礎編をさらに詳しく解説し(書籍版第3章)、応用編としてモーション、イベント、レイアウト、地図の作成法、データのエクスポート(PDFやSVG等)の章が追加されています(同9章~13章)。アマゾンのページで目次を見ることができます。

本チュートリアルがわかりにくいと感じられた方、あるいは本チュートリアルを終え、さらに応用力を身につけたいと思われた方のどちらにもお勧めの内容となっています。

翻訳はコンピュータ・プログラミング関連書籍を多数翻訳されている長尾高弘氏です。