ぼくのかんがえたさいきょうの円グラフ(d3.js)

公開日:2019-05-31
最終更新:2019-06-01

はじめに

d3のバージョンはv4です。バージョンによって書き方が違うのでご注意ください。
グラフのデータはこちらを使用させていただきました。

完成品

円グラフにも色々な用途があるので難しいところですが、こんな感じになります。(配色がg〇〇gleっぽいことに後で気付いた)
カーソルが見えないですが、円グラフの水色の部分にある状態です。

コード

graph_pie.jsは以下のようになります。

//------------------------------graph_pie.js-----------------------------------  
/**  
 * この関数を呼び出すと円グラフが作成される  
 * @param  name 寄生先のクラス名。  
 * @param  data データ。  
 * @param  fillcolor 配色。  
 * @param  length グラフの長さ(円グラフの直径)  
 */  
function graph_pie(name, data, fillcolor, length) {  
    //関数が呼び出されたことを確認  
    console.log(name + " is called");  

    //初期設定-------------------------------------------------------------------  
    let margin = {  
        'top': 10,  
        'left': 5,  
        'right': 5,  
        'bottom': 100 //グラフの説明の為のスペース  
    }  
    //データの合計を出す  
    let all = d3.sum(data, function (d) {  
        return d.value;  
    });  

    //svgを作成。ここで寄生している-----------------------------------------------  
    let svg = d3.select("." + name).append("svg")  
        .attr("width", length + margin.left + margin.right)  
        .attr("height", length + margin.top + margin.bottom);  

    //グラフに関する初期設定  
    let radius = length / 2,  
        pie = d3.pie().value(function (d) {  
            return d.value;  
        }).sort(null),  
        arc = d3.arc().outerRadius(radius * 0.9).innerRadius(radius * 0.5);  

    //グラフを描写する範囲の設定  
    let graph = svg.append("g")  
        .attr("transform", "translate(" + (radius + margin.left) + "," + (radius + margin.top) + ")");  

    //円グラフの一つ一つのピースを割り当てる  
    let arcs = graph.selectAll(".arc").data(pie(data)).enter()  

    //各ピースに肉付け  
    arcs.append("path").attr("class", "arc")  
        .attr("fill", function (d, i) {  
            return fillcolor[i];  
        }).attr("d", arc)  
        .attr("stroke", "white")  
        .style("stroke-width", 3)  
        .on("mouseover", function (d) {  
            d3.select(this).attr("d", d3.arc().outerRadius(radius).innerRadius(radius * 0.4));  
        })  
        .on("mouseout", function () {  
            d3.select(this).attr("d", arc);  
        });  
    arcs.append("text").attr("transform", function (d) {  
            return "translate(" + arc.centroid(d) + ")";  
        }).attr("fill", "white").attr("font-size", "20")  
            .style("font-weight", "600")  
            .attr("text-anchor", "middle")  
            .text(function (d) {  
                //小さすぎたら値は描写しないようにする  
                if (d.value / all > 0.1) {  
                    return d.value;  
                }  
                return "";  
            });  

    //円グラフの中央のテキストの設定  
    graph.append("text")  
        .attr("transform", "translate(0," + (-20) + ")")  
        .style("text-anchor", "middle")  
        .attr("fill","#454545")  
        .style("font-weight", "600")  
        .style("font-size", 20)  
        .text("総量");  
    graph.append("text")  
        .attr("transform", "translate(0," + 20 + ")")  
        .style("text-anchor", "middle")  
        .attr("fill","#454545")  
        .style("font-weight", "600")  
        .style("font-size", 40)  
        .text(all);  

    //凡例----------------------------------------------------------------------  
    let tip_size = length / data.length;  
    let legend = svg.append("g").attr("transform", function (d) {  
        return "translate(0," + (length + margin.top) + ")";  
    });  

    //データの数分チップを生成  
    let tips = legend.selectAll(".tips").data(data).enter()  
        .append("g").attr("class", "tips").attr("transform", function (d, i) {  
            return "translate(" + (tip_size * i + margin.left) + ",0)";  
        });  

    //各チップに肉付け  
    tips.append("rect").attr("rx","20").attr("width",tip_size).attr("height",margin.bottom)  
        .attr("opacity","0.9")  
        .attr("fill", function (d, i) {  
            return fillcolor[i];  
        });  
    tips.append("text").attr("transform", "translate(" + (tip_size / 2) + "," + (margin.bottom / 4) + ")")  
        .style("text-anchor", "middle")  
        .attr("font-size", "12")  
        .style("font-weight", "600")  
        .attr("fill", "white")  
        .text(function (d) {  
            return d.name;  
        });  
    tips.append("text").attr("transform", "translate(" + (tip_size / 2) + "," + (margin.bottom / 4 * 3) + ")")  
        .style("text-anchor", "middle")  
        .attr("font-size", "20")  
        .style("font-weight", "600")  
        .attr("fill", "white")  
        .text(function (d) {  
            return Math.round(d.value / all * 100) / 100 + "%";  
        });  
}  

//配色とデータの形式はこんな感じ  
var color = ["#00a1e9", "#37a34a","#f39800", "#b33e5c"];  
var data = [  
    { "name": "角換わり", "value": 150 },  
    { "name": "矢倉", "value": 96 },  
    { "name": "相掛かり", "value": 86 },  
    { "name": "横歩取り", "value": 81 }  
];  
//関数の呼び出し  
graph_pie("testpie", data, color, 400);  

もちろん、出力したいhtmlファイルでd3とこのファイルの読み込みブロックの追加を忘れずに

d3の読み込み

<script src="http://d3js.org/d3.v4.min.js" charset="utf-8"></script>  

graph_pie.jsの読み込み

<script type="text/javascript" src='graph_pie.js'></script>  

ブロックの追加

<div class="testpie"></div> <!--関数の第一引数nameと同じにする-->  

解説...

解説したいけれど、コードが思ったより長くなったのでログに追加する予定(上がったらここにリンクを張ります)

まとめ

テキストのサイズや凡例の縦の長さも可変にしたいが、コードがさらに長くなると考え断念。。。柔軟性を持たせるにはそこら辺を実装する必要がありそう。

付録

このコードを少しいじると下のようなデザインを作ることができます。


記事が少しでもいいなと思ったらクラップを送ってみよう!
45
+1
@syakooのブログ

よく一緒に読まれている記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる

技術ブログをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

技術ブログを開設する

Qrunchでアウトプットをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

Markdownで書ける

ログ機能でアウトプットを加速

デザインのカスタマイズが可能

技術ブログ開設

ここから先はアカウント(ブログ)開設が必要です

英数字4文字以上
.qrunch.io
英数字6文字以上
ログインする