selection.data - データを関連付ける
投稿日: / 更新日:
d3.jsのselection.data()
は、要素にデータをまとめて関連付けるためのAPIです。
サンプルコード
<ul>
<li>1つ目のLI</li>
<li>2つ目のLI</li>
<li>3つ目のLI</li>
<li>4つ目のLI</li>
<li>5つ目のLI</li>
</ul>
// 全てのli要素を選択 (5個)
d3.selectAll( "li" )
// 選択したd3.selectionオブジェクトにデータ(配列)を関連付ける (5個分)
.data( [ "1個目のLI", "2個目のLI", "3個目のLI", "4個目のLI", "5個目のLI" ] )
// 各li要素のテキストを、関連付けたデータに応じて変更する
.text( function(d) { return d ; } ) ;
デモ
仕組み
まずは、全てのli
要素をselectAll()
を使って選択状態にします。d3.selectionオブジェクト(selection
)の中には、5個のli
要素が含まれます。
<ul>
<li>1つ目のLI</li>
<li>2つ目のLI</li>
<li>3つ目のLI</li>
<li>4つ目のLI</li>
<li>5つ目のLI</li>
</ul>
// 全てのli要素を選択 (5個)
var selection = d3.selectAll( "li" ) ;
次に、data()
に配列を指定して、その配列をd3.selectionオブジェクトの各要素に関連付けます。li
要素が5個含まれているので、ここでは5つの要素を持った配列を指定しました。ここまでがdata()
の役割です。配列を使って、複数の要素にまとめてデータを関連付けられるのがdata()
なんです。逆に個別の要素にデータを関連付けたいなら、datum()
というメソッドを使って下さい。
// 選択したd3.selectionオブジェクトの各要素にデータ(配列)を関連付ける
selection.data( [ "1個目のLI", "2個目のLI", "3個目のLI", "4個目のLI", "5個目のLI" ] ) ;
// 次のようにデータが関連付けられた
// <li>1つ目のLI</li> = 1個目のLI
// <li>2つ目のLI</li> = 2個目のLI
// <li>3つ目のLI</li> = 3個目のLI
// <li>4つ目のLI</li> = 4個目のLI
// <li>5つ目のLI</li> = 5個目のLI
さて、関連付けられたデータは一体どのように活用できるのか、確認しておきましょう。5つのli
要素に対して何らかの処理をします。ここでは、テキストを変更するtext()
というメソッドを使いましょう。
// text()でテキストを変更する
selection.text() ;
text()
は引数を指定しないとダメですよね。例えば、次のように引数に文字列を指定した場合、どうなるでしょう?答えは、5個のli
要素のテキストがみんなSYNCER
になります。
// 引数に文字列を指定する
selection.text( "SYNCER" ) ;
それでは、文字列ではなく関数を指定するとどうなるでしょう?答えは、その関数の戻り値が、text()
の引数として指定される、です。下記の場合、関数の戻り値はSYNCER
なので、先ほどと同じく、5個のli
要素のテキストがみんなSYNCER
になりますね。
// 引数に関数を指定する
selection.text( function() { return "SYNCER" ; } ) ;
ここが肝です。この関数は何回実行されるでしょう?答えは5回です。d3.selectionオブジェクトの中身(li
要素)が5個あるからですね。最初のli
要素から、最後のli
要素まで、順々に関数を実行していくわけです。曖昧に「関数が全部のli要素に反映される」という捉え方ではなく、「各要素に1回ずつ関数が実行される」というのを強くイメージして下さい。
// 引数に関数を指定する
selection.text( function() { return "SYNCER" ; } ) ;
// 1個目のli要素に対して
function() { return "SYNCER" ; }
// 2個目のli要素に対して
function() { return "SYNCER" ; }
// 3個目のli要素に対して
function() { return "SYNCER" ; }
// 4個目のli要素に対して
function() { return "SYNCER" ; }
// 5個目のli要素に対して
function() { return "SYNCER" ; }
この関数は2つの引数をとります。その1つ目の引数が肝心のdata()
でその要素に関連付けた値なんです。2つ目の引数はインデックス番号です。インデックス番号というのは、d3.selectionオブジェクトにおけるその要素の順番、位置ですね。テキストだと分かりにくいですが、下記を見ればピンとくるはずです。このように、data()
で要素に関連付けられた値を関数で利用できるわけです。
// 引数に関数を指定する
selection.text( function( d, i ) {
// d=その要素に関連付けられたデータ
// i=インデックス番号
// this=要素
return d ;
} ) ;
// 1個目のli要素に対して
function( d, i ) {
// d="1個目のLI"
// i=0
}
// 2個目のli要素に対して
function( d, i ) {
// d="2個目のLI"
// i=1
}
// 3個目のli要素に対して
function( d, i ) {
// d="3個目のLI"
// i=2
}
// 4個目のli要素に対して
function( d, i ) {
// d="4個目のLI"
// i=3
}
// 5個目のli要素に対して
function( d, i ) {
// d="5個目のLI"
// i=4
}
つまり、次のように関数を指定することで、各要素に関連付いたデータを元に、別々の値を振り分けることができるんです。
// 引数に文字列を指定する
selection.text( function( d, i ) { return d ; } ) ;
// この章の例の場合、下記のように応用もできます
// selection.text( function( d, i ) { return ( i + 1 ) + "個目のLI" ; } ) ;
// li要素は次のように変わるでしょう
// <ul>
// <li>1個目のLI</li>
// <li>2個目のLI</li>
// <li>3個目のLI</li>
// <li>4個目のLI</li>
// <li>5個目のLI</li>
// </ul>
高度な応用として、data()
に指定する1つ1つの値を配列、またはオブジェクトリテラルにすることで、1つ1つの要素に複数の値を組み合わせて指定していくことができます。例えば、style()
で背景色をランダムに変更する場合を考えてみましょう。下記のように1つ1つの値を配列に指定すれば、1個目は「赤か青」、2個目は「緑かピンク」、3個目は「紫か珊瑚色」というように、別々に背景色を変えることができます。
// 全てのli要素を選択 (5個)
var selection = d3.selectAll( "li" ) ;
// 配列を関連付ける
selection.data( [
[ "red", "blue" ] , // 1個目のli要素に関連付ける
[ "green", "pink" ] , // 2個目のli要素に関連付ける
[ "purple", "coral" ] , // 3個目のli要素に関連付ける
[ "brown", "black" ] , // 4個目のli要素に関連付ける
[ "cyan", "orangered" ] // 5個目のli要素に関連付ける
] ) ;
// スタイルを変更
selection.style( "background", function( d, i ) {
// 1個目のli要素の場合
// d=[ "red", "blue" ]
// i=0
// d3.shuffle()は、引数に指定した配列をシャッフルするメソッドです
// シャッフルした後の第1要素を戻り値に指定しています
return d3.shuffle( d )[0] ;
} ) ;
構文
selection = selection.data( dataSet [, function] )
項目 | 説明 |
---|---|
dataSet | 第1引数に、関連付けたいデータを配列で指定する。 |
function | 省略可。第2引数に関数を指定すると、この直前の別のdata() を引数にした関数が実行される。2016年3月現在、活用方法が分からなかったので説明ができません。ご了承下さい。 |
項目 | 説明 |
---|---|
selection | データを関連付けたd3.selectionオブジェクトが戻り値となる。 |