d3.js(v5) で円グラフ表示する方法について記載します。
実装すると、次のような円グラフが表示できます。
目次
1.全体のコード
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 93 94 95 96 97 98 99 100 101 |
<!DOCTYPE html> <html> <head> <title>d3 circle chart</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="js/d3.min.js"></script> <style type="text/css"> .bar { fill: steelblue; } .axis text { font: 10px sans-serif; color: #333; } #chart{ width:600px; height:600px; } </style> </head> <body> <svg id="chart"></svg> <script> var data = [ {name: "A", value: 5000}, {name: "B", value: 2500}, {name: "C", value: 1250}, {name: "D", value: 1000}, {name: "E", value: 250}, ]; var width = 500; var height = 500 // dataの nameごとにグラフで使用する色を設定 var color = d3.scaleOrdinal() .domain(data.map(d => d.name)) .range(d3.quantize(t => d3.interpolateSpectral(t * 0.8 + 0.1), data.length).reverse()); // 円グラフの内側・外側半径の設定 var arc = d3.arc() .innerRadius(0) .outerRadius(Math.min(width, height) / 2 - 1); // 円グラフのラベル表示位置を設定 const radius = Math.min(width, height) / 2 * 0.57; var arcLabel = d3.arc().innerRadius(radius).outerRadius(radius); // 円グラフ作成用の角度を計算 var arcs = d3.pie() .sort(null) // data配列の順番でグラフを作成(未指定の場合は、valueの降順) .value(function(d) { return d.value; }) (data); // 円グラフ描画エリアを選択 var svg = d3.select("#chart") .attr("text-anchor", "middle") .style("font", "12px sans-serif") // g要素を追加 const g = svg.append("g") .attr("transform", `translate(${width / 2},${height / 2})`); // g要素に各データのpath要素を追加 g.selectAll("path") .data(arcs) .enter().append("path") .attr("fill", d => color(d.data.name)) .attr("stroke", "white") .attr("d", arc) .append("title") .text(d => `${d.data.name}: ${d.data.value.toLocaleString()}`); // データごとにtext要素を設定 const text = g.selectAll("text") .data(arcs) .enter().append("text") .attr("transform", d => `translate(${arcLabel.centroid(d)})`) .attr("dy", "0.35em"); // text要素にデータ名を設定(dataのnameを設定) text.append("tspan") .attr("x", 0) .attr("y", "-0.7em") .style("font-weight", "bold") .text(d => d.data.name); // text要素にデータ名を設定(dataのvalueを設定) text.filter( d => (d.endAngle - d.startAngle) > .7535).append("tspan") .attr("x", 0) .attr("y", "0.7em") .attr("fill-opacity", 0.7) .text(d => d.data.value.toLocaleString()); </script> </body> </html> |
2.コードの詳細( HTML )
グラフを表示する場所を定義します。
1 |
<svg id="chart"></svg> |
3.コードの詳細( JavaScript )
3−1.円グラフの内側・外側半径の設定
内側半径(innerRadius)、外側半径(outerRadius) を設定しています。
内側半径を大きくしていくと、ドーナッツ型の円グラフを作成することもできます。
1 2 3 |
var arc = d3.arc() .innerRadius(0) .outerRadius(Math.min(width, height) / 2 - 1); |
3−2.円グラフのラベル表示位置を設定
円グラフ上に表示するラベルの表示位置を計算、設定しています。
Math.min(width, height) / 2 で半径を計算し、そこに任意の値(0.57)を掛けて表示位置を計算しています。
グラフに合わせて調整する項目になります。
1 2 3 |
// 円グラフのラベル表示位置を設定 const radius = Math.min(width, height) / 2 * 0.57; var arcLabel = d3.arc().innerRadius(radius).outerRadius(radius); |
3−3.各データごとの角度を計算
各要素の値(value)から必要になる角度を計算します
sortにnullを指定しているのは、デフォルトでvalueの降順でソートされるためです。
nullを指定することにより、data配列の順番で表示されるようにしています。
1 2 3 4 |
var arcs = d3.pie() .sort(null) // data配列の順番でグラフを作成(未指定の場合は、valueの降順) .value(function(d) { return d.value; }) (data); |
3−4.g要素に各データのpath要素を追加
各データごとにpath要素を作成します。
ここでは、円グラフを描画するためのデータ(arcs)や各要素の色(fill)などを指定します。
1 2 3 4 5 6 7 8 |
g.selectAll("path") .data(arcs) .enter().append("path") .attr("fill", d => color(d.data.name)) .attr("stroke", "white") .attr("d", arc) .append("title") .text(d => `${d.data.name}: ${d.data.value.toLocaleString()}`); |
3−5.text要素にデータ名を設定(dataのvalueを設定)
textの設定では、全体のコード通りなのですが1つポイントがあります。
以下のように、text.filter としているのは、値が小さいデータにはテキストを表示しないようにするためです。
1 2 3 4 5 6 |
// text要素にデータ名を設定(dataのvalueを設定) text.filter( d => (d.endAngle - d.startAngle) > .7535).append("tspan") .attr("x", 0) .attr("y", "0.7em") .attr("fill-opacity", 0.7) .text(d => d.data.value.toLocaleString()); |
値が小さいデータは、円グラフ上のスペースが狭いので、テキストを表示してしまうと他のデータに被ってしまうため、ここでは閾値(.7535より大きい)を指定して、テキストの表示・非表示を行っています。
DemoのDとEのデータには、テキストが表示されていないのはこのためです。
.7535と指定している閾値ですが、大体以下の値で指定できます。
データが全体の50%以上の場合に、テキストを表示する
d => (d.endAngle – d.startAngle) > 3.14
データが全体の25%以上の場合に、テキストを表示する
d => (d.endAngle – d.startAngle) > 1.57
4.まとめ
d3.jsを使用して円グラフを作成しました。
テキストの表示は、使用するデータにより閾値を調整する必要がありますが、簡単に円グラフを作成できると思います。