D3.js v4/v5 サンバースト図の作り方
D3によるサンバースト(sun burst)図の作り方を紹介します。
サンプルデモ
サンプルプログフラム
| 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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | <!DOCTYPE html> <html> <head>   <meta charset="utf-8">   <title>D3 sunburst v4/v5</title>   <script src="https://d3js.org/d3.v5.min.js"></script> </head> <body>   <script>   // 1. 描画用のデータ準備   var width = 800;   var height = 600;   var radius = Math.min(width, height) / 2;   var data = {     "name": "A",     "children": [       { "name": "B", "value": 25 },       {         "name": "C",         "children": [{ "name": "D", "value": 10 }, { "name": "E", "value": 15 }, { "name": "F", "value": 10 }]       },       { "name": "G", "value": 15 },       {         "name": "H",         "children": [{ "name": "I", "value": 20 }, { "name": "J", "value": 10 }]       },       { "name": "K", "value": 10 }     ]   };   // 2. SVG表示用要素の設定   var svg = d3.select("body").append("svg").attr("width", width).attr("height", height);   g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + (height / 2) + ")");   // 3. 描画用スケールの設定   var colorScale = d3.scaleOrdinal().range([     "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"   ]);   var rScale = d3.scaleLinear()     .domain([0, radius])     .range([0.4 * radius, radius]);   // 4. 描画用のデータ変換   root = d3.hierarchy(data);   root.sum(function(d) { return d.value; })     .sort(function(a, b) { return b.height - a.height || b.value - a.value; });   var partition = d3.partition()     .size([2 * Math.PI, radius]);   partition(root);   // 5. SVG要素の設定   var arc = d3.arc()     .startAngle(function(d) { return d.x0; })     .endAngle(function(d) { return d.x1; })     .innerRadius(function(d) { return rScale(d.y0); })     .outerRadius(function(d) { return rScale(d.y1); });   g.selectAll("path")     .data(root.descendants())     .enter()     .append("path")     .attr("d", arc)     .attr('stroke', '#fff')     .attr("fill", function(d) {       while(d.depth > 1) d = d.parent;       if(d.depth == 0) return "lightgray";       return colorScale(d.value);     })     .attr("opacity", 0.8)     .append("title")     .text(function(d) { return d.data.name + "\n" + d.value; });   g.selectAll("text")     .data(root.descendants())     .enter()     .append("text")     .attr("fill", "black")     .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })     .attr("dy", "5px")     .attr("font", "10px")     .attr("text-anchor", "middle")     .text(function(d) { return d.data.name; });   </script> </body> </html> | 
解説
サンバースト図は、partitionと円グラフの組み合わせで作成します。それぞれの詳細はリンク先を参照ください。
1. 描画用のデータ準備
サンバースト用のデータ構造は、hierarchy用のデータ構造と同様に設定します。
2. SVG表示用要素の設定
SVGを表示するための”svg”要素を”body”内に設定します。また、サンバースト図の中心座標が(0,0)になるため、描画領域の中心に”g”要素を設定しその中にサンバースト図の要素を設定していきます。
| 1 2 |   var svg = d3.select("body").append("svg").attr("width", width).attr("height", height);   g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + (height / 2) + ")"); | 
3. 描画用スケールの設定
色分けのためのカラースケールを設定します。カラースケールの作り方はこちらを参照ください。
| 1 2 3 |   var colorScale = d3.scaleOrdinal().range([     "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"   ]); | 
また、中心を空洞にして半径方向の方向の位置を調整するためのスケールを設定します。
| 1 2 3 |   var rScale = d3.scaleLinear()     .domain([0, radius])     .range([0.4 * radius, radius]); | 
d3.scaleLinear()は.domainで設定したレンジを.rangeで設定したレンジに変更する関数をrScaleに設定するものです。
4. 描画用のデータ変換
用意したデータをd3.hierarchy()とd3.partition()を使って階層構造用データ、partition用データと変換します。この時、partitionのサイズを[角度最大値、半径最大値]としておくことで円グラフに変換できるようにします。
| 1 2 3 4 5 6 7 8 |   root = d3.hierarchy(data);   root.sum(function(d) { return d.value; })     .sort(function(a, b) { return b.height - a.height || b.value - a.value; });   var partition = d3.partition()     .size([2 * Math.PI, radius]);   partition(root); | 
5. SVG要素の設定
円グラフと同様に、SVGの”pash”要素の”d”属性を算出するメソッドを呼び出します。
| 1 2 3 4 5 |   var arc = d3.arc()     .startAngle(function(d) { return d.x0; })     .endAngle(function(d) { return d.x1; })     .innerRadius(function(d) { return rScale(d.y0); })     .outerRadius(function(d) { return rScale(d.y1); }); | 
SVGの”path”要素を使ってサンバースト図を表示します。”fill”属性は2番目の深さの親を探索して親の値に応じて色を切り替える設定にしています。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |   g.selectAll("path")     .data(root.descendants())     .enter()     .append("path")     .attr("d", arc)     .attr('stroke', '#fff')     .attr("fill", function(d) {       while(d.depth > 1) d = d.parent;       if(d.depth == 0) return "lightgray";       return colorScale(d.value);     })     .attr("opacity", 0.8)     .append("title")     .text(function(d) { return d.data.name + "\n" + d.value; }); | 
root.descendants()は、入れ子に階層構造のrootから要素を取り出して配列とするものです。
サンバースト図上位テキストのラベルを設定します。
| 1 2 3 4 5 6 7 8 9 10 |   g.selectAll("text")     .data(root.descendants())     .enter()     .append("text")     .attr("fill", "black")     .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })     .attr("dy", "5px")     .attr("font", "10px")     .attr("text-anchor", "middle")     .text(function(d) { return d.data.name; }); | 
arc.centroid()は円グラフのパイの中心座標を算出するメソッドです。
まとめ
サンバースト図は、D3.jsの解説本の表紙にもなっているものです。インパクトのあるビジュアルを作成できます。クリック部分を拡大する操作も可能です。こちらを参照ください。




