パックレイアウトは階層(親子)関係を利用してチャートを表すものです。D3.jsではパックレイアウトは階層化レイアウト機能の1つとしてあります。
パックレイアウト作成の基本
パックレイアウトを作成するには階層化されたJavaScriptオブジェクトがなければなりません。パックレイアウトに最低限必要なデータは、親となるデータです。
簡単に言うと、下記のようなvalueプロパティだけあれば大丈夫です。
1 |
var arrData = { value:40 } |
valueはパックレイアウトでデフォルトで使用されているプロパティ名です。value以外の値を使用したいときは、専用のメソッドを使わなければなりません。パックレイアウトを使用するには、d3.layout.pack()メソッドを使います。パックレイアウトは表現する範囲をsize()メソッドで指定します。パラメータは配列形式で横幅、高さを指定できます、
後は、今までと同じようにsvg要素に対してcircle要素を追加します。違う点はデータセットの部分です。data()メソッドには、下記のようにして、nodes()メソッドを使う必要があります。
1 |
data( 変数名.nodes(arrData)); |
上記のようにデータを設定するとD3.jsの内部で計算が行われて、以下の表のプロパティが計算が実行されます。
プロパティ名 | 詳細 |
---|---|
parent | 親階層のノード。ルート(一番上の階層)の場合はnull |
children | 子ノード。ない場合はnull |
value | 値 |
depth | 階層の深さ、ルートの場合は0 |
x | 円の中心X座標 |
y | 円の中心Y座標 |
r | 円の半径 |
attr()メソッドを使い要素に値を設定する場合は、上記の表のプロパティから読み出します。
サンプルコードの実行結果はこちら
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<!DOCTYPE html> <head> <meta charset="utf-8"> <title>パックレイアウトを表示する</title> <script src="../js/d3.js"></script> <style> svg{ width:320px; height:320px; border:2px solid black; } circle{ fill:none; stroke:blue; } </style> </head> <body> <h1>パックレイアウトを表示</h1> <svg id="graph"></svg> <script src="test.js"></script> </body> </html> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
/* パックレイアウトを表示 */ var svgEle = document.getElementById("graph"); var svgWidth = getComputedStyle( svgEle, null) .getPropertyValue("width"); var svgHeight = getComputedStyle( svgEle, null) .getPropertyValue("height"); svgWidth = parseFloat( svgWidth ); svgHeight = parseFloat( svgHeight ); var packData = { value: 40 } var bubble = d3.layout.pack() .size([320,320]); d3.select("#graph") .selectAll("circle") .data( bubble.nodes(packData)) // データセットを要素に追加 .enter() .append("circle") // データの数だけcircle要素追加 .attr("r", function(d){ // 半径指定 return d.r; }) .attr("cx", function(d){ // 中心のX座標を指定 return d.x; }) .attr("cy", function(d){ // 中心のY座標を指定 return d.y; }) |
上記の散布うコードを実行するとデータが1つだけなので1つの円しか表示されません。次は、円の中に円が入っている(階層化されている・入れ子になっている)データを用意します。入れ子にするにはchildrenプロパティを使い配列形式データを用意します。
データはvalueプロパティを使って指定します。下記のように書きます。
1 2 3 4 5 6 7 8 |
var packData = { value: 40, children : [ { value: 30 }, { value: 100 }, { value: 200 } ] } |
サンプルコードの実行結果はこちら
●HTMLファイルは一番上のサンプルと同じです。
●JSファイルも上記のvar packData の箇所のみ変更しているだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
/* パックレイアウトを表示 */ var svgEle = document.getElementById("graph"); var svgWidth = getComputedStyle( svgEle, null) .getPropertyValue("width"); var svgHeight = getComputedStyle( svgEle, null) .getPropertyValue("height"); svgWidth = parseFloat( svgWidth ); svgHeight = parseFloat( svgHeight ); var packData = { value: 40, children : [ { value: 30 }, { value: 100 }, { value: 200 } ] } var bubble = d3.layout.pack() .size([320,320]); d3.select("#graph") .selectAll("circle") .data( bubble.nodes(packData)) // データセットを要素に追加 .enter() .append("circle") // データの数だけcircle要素追加 .attr("r", function(d){ // 半径指定 return d.r; }) .attr("cx", function(d){ // 中心のX座標を指定 return d.x; }) .attr("cy", function(d){ // 中心のY座標を指定 return d.y; }) |
上記のファイルを実行すると円の中に円が表示されています。ということは、children配列の中にchildrenを入れれば、いくらでも入れ子にすることができます。その計算をD3.js側で自動で行ってくれます。下記のサンプルコードを実行すると確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var packData = { value: 100, children : [ { value: 80 }, { value: 40 }, { value: 20 }, { value: 120, children : [ { value : 90 }, { value : 50 } ] } ] } |
サンプルコードの実行結果はこちら
●HTMLファイルは一番上のサンプルと同じです。
●JSファイルも上記のvar packData の箇所のみ変更しているだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
/* パックレイアウトを表示 */ var svgEle = document.getElementById("graph"); var svgWidth = getComputedStyle( svgEle, null) .getPropertyValue("width"); var svgHeight = getComputedStyle( svgEle, null) .getPropertyValue("height"); svgWidth = parseFloat( svgWidth ); svgHeight = parseFloat( svgHeight ); var packData = { value: 100, children : [ { value: 80 }, { value: 40 }, { value: 20 }, { value: 120, children : [ { value : 90 }, { value : 50 } ] } ] } var bubble = d3.layout.pack() .size([320,320]); d3.select("#graph") .selectAll("circle") .data( bubble.nodes(packData)) // データセットを要素に追加 .enter() .append("circle") // データの数だけcircle要素追加 .attr("r", function(d){ // 半径指定 return d.r; }) .attr("cx", function(d){ // 中心のX座標を指定 return d.x; }) .attr("cy", function(d){ // 中心のY座標を指定 return d.y; }) |
円にアニメーションと色を付けてみます。
円のサイズを0に指定してkらtransition()メソッドを使いアニメーション処理を行うようにしてます。transition()メソッド、duration()メソッド後に、最終的な円のサイズを指定すれば完了です、
サンプルコードの実行結果はこちら
●HTMLファイルは一番上のサンプルと同じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
/* パックレイアウトを表示 */ var svgEle = document.getElementById("graph"); var svgWidth = getComputedStyle( svgEle, null) .getPropertyValue("width"); var svgHeight = getComputedStyle( svgEle, null) .getPropertyValue("height"); svgWidth = parseFloat( svgWidth ); svgHeight = parseFloat( svgHeight ); var packData = { value: 100, children : [ { value: 80 }, { value: 40 }, { value: 20 }, { value: 120, children : [ { value : 90 }, { value : 50 } ] } ] } var color = d3.scale.category10(); // 10色指定 var bubble = d3.layout.pack() .size([320,320]); d3.select("#graph") .selectAll("circle") .data( bubble.nodes(packData)) // データセットを要素に追加 .enter() .append("circle") // データの数だけcircle要素追加 .attr("r", 0) // アニメーション前は半径0 .attr("cx", function(d){ // 中心のX座標を指定 return d.x; }) .attr("cy", function(d){ // 中心のY座標を指定 return d.y; }) .transition() .duration(function(d,i){ return d.depth * 500 + 500; // 入れ子の深さに応じて待ち時間を設定 }) .attr("r", function(d){ // 半径指定 return d.r; }) .style("fill",function(d,i){ return color(i); }); |