D3.js レイアウト – d3.layout.treemapでツリーマップを作る

Share

ツリーマップは、ツリー構造のデータを使って四角形の入れ子を表示していくチャートです。表示形式は違えど、やっていることは以前の
D3.js レイアウト – d3.tree.layoutでツリーを作るD3.js レイアウト – d3.layout.packでパックチャートとほぼ同じです。したがって使うデータの形式も同じですが、一応載せておきます。

{
 "name": "明治",
 "種類": [
  {
   "name": "チョコ菓子シリーズ",
   "種類": [
    {
     "name": "きのこの山",
     "種類": [
      {"name": "味わいミント", "好き度": 10},
 	 {"name": "黒糖きなこ", "好き度": 5},
      {"name": "チョコバナナ", "好き度": 15}
     ]
    },
    {
     "name": "たけのこの里",
     "種類": [
      {"name": "マカダミアクッキー", "好き度": 10},
      {"name": "焼き栗", "好き度": 2}
     ]
    },
	{
	"name": "すぎのこ村", "好き度": 20
	}
   ]
  }
 ]
}

ツリーマップの設定を作るには、以下のようにします。
size()でツリーマップ全体の大きさ。
value()で四角形の大きさに関する値の名前を関数で指定。この場合は”好き度”。
children()で入れ子に使う名前を関数で指定。この場合は”種類”。

var treemap = d3.layout.treemap()
.size([width, height - 100])
.value(value) // 値の名前を指定。
.children(children); // 入れ子の名前を指定。

function value(d) {
  return d["好き度"];
}

function children(d) {
  return d["種類"];
}

これを使ってデータを変換するには以下のようにします。
こうすると、データの親子関係と値に合った四角形のデータを自動的に計算して出してくれます。
xとyは、各四角形の左上の位置。
dxとdyは各四角形のwidthとheight。
areaは面積。
depthは親子関係の深さで、一番上の親が0で、子になるほど数が大きくなります。

// x,y,dx,dy,area,depthが出る。
var areas = treemap.nodes(data);

このデータを使って、rectで四角形を作っていくと、ツリーマップが出来上がります。
では実際に作ってみます。

 

ツリーマップを作る

結果:

d3レイアウト-treemap1
クリックすると実際のページが開きます。

コード:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
</head>
<body>

	<script src="http://d3js.org/d3.v3.min.js"></script>

	<script>
	var width = 700;
	var height = 600;

	var svg = d3.select("body").append("svg")
	.attr("width", width)
	.attr("height", height)
	.attr("transform","translate(50,50)");

	var color10 = d3.scale.category10();

	// ツリーマップの設定。
	var treemap = d3.layout.treemap()
	.size([width, height - 100])
	.value(value) // 値の名前を指定。
	.children(children); // 入れ子の名前を指定。

	function value(d) {
	  return d["好き度"];
	}

	function children(d) {
	  return d["種類"];
	}

	d3.json("kinoko_takenoko.json", function(data) {

// x,y,dx,dy,area,depthが出る。
var areas = treemap.nodes(data);

	console.log(areas);

	var cells = svg.selectAll(".cell")
	.data(areas)
	.enter()
	.append("g")
	.attr("class","cell");

	cells.append("rect")
	.attr("x", function(d){ return d.x; })
	.attr("y", function(d){ return d.y; })
	.attr("width", function(d){ return d.dx; })
	.attr("height", function(d){ return d.dy; })
	.attr("fill",function(d){ return d.children ? null : color10(d.parent.name); }) // 一番下の子だけ親に合わせて色を変える。
	.attr("stroke", "white")
	.attr("stroke-width",2)
	.attr("opacity", 1); // 重なった円が見えるように透明度をつける。

	cells.append("text")
	.attr("x", function(d){ return d.x + (d.dx/2); }) // 各rectの真ん中に配置。
	.attr("y", function(d){ return d.y + (d.dy/2); }) // 各rectの真ん中に配置。
	.attr("text-anchor","middle")
	.text(function(d){ return d.children ? "" : d.name; }) // 一番下の子の名前だけ表示。
	.attr("stroke", "black");

	});

	</script>

</body>
</html>

解説:
設定とデータ変換はすでに説明したとおりです。

実際に四角形を作る時は、rectのxとyにはデータのx、y。widthとheightにはデータのdxとdyを入れます。
色は親の違いで分けたいので、子を持つ親は色を持たずに、一番下の子だけはcolor10(d.parent.name)で親の名前によって色を変えています。

cells.append("rect")
.attr("x", function(d){ return d.x; })
.attr("y", function(d){ return d.y; })
.attr("width", function(d){ return d.dx; })
.attr("height", function(d){ return d.dy; })
.attr("fill",function(d){ return d.children ? null : color10(d.parent.name); }) // 一番下の子だけ親に合わせて色を変える。
.attr("stroke", "white")
.attr("stroke-width",2)
.attr("opacity", 1);

テキストは各四角形の中央に配置するために、xとyをd.x + (d.dx/2)とd.y + (d.dy/2)にしています。
さらに中央揃えにするために、text-anchorという属性でmiddleを指定しています。
テキストの内容はd.children ?で条件分岐しています。子があるものは””で何も表示しないで、自分の子を持たない一番下の子の名前だけd.nameで表示しています。

cells.append("text")
.attr("x", function(d){ return d.x + (d.dx/2); }) // 各rectの真ん中に配置。
.attr("y", function(d){ return d.y + (d.dy/2); }) // 各rectの真ん中に配置。
.attr("text-anchor","middle")
.text(function(d){ return d.children ? "" : d.name; }) // 一番下の子の名前だけ表示。
.attr("stroke", "black");

 

sliceとdiceで並びを変える

さらにオプションとして並びを変えることができます。
それにはツリーマップの設定で、mode()の中にslice , dice , slice-diceのどれかを入れるだけです。

var treemap = d3.layout.treemap()
.size([width, height - 100])
.value(value)
.children(children)
.mode("slice-dice"); //slice , dice , slice-dice

モードごとの結果:

d3レイアウト-treemap2slice
slice
d3レイアウト-treemap3dice
dice
d3レイアウト-treemap4slide-dice
slice-dice

コメントを残す