2016年3月16日水曜日

【TypeScript/JavaScript】d3.jsでグラフを作ろう(円グラフ)

TypeScript及びJavaScriptを使って、グラフ作成する方法で、d3.jsを使う方法があります。
前回に続いて、グラフのつくり方を纏めてみました。


(1)データ
キー(label/value)と値(labelに対する値/valueに対する値)に値を設定したJsonデータを作成します。

            res = [
                { label: "USD/JPY", value: 87 }
                , { label: "GBP/JPY", value: 6 }
                , { label: "EUR/USD", value: 3 }
                , { label: "CHF/JPY", value: 2 }
                , { label: "AUD/JPY", value: 1 }
                , { label: "EUR/JPY", value: 1 }
            ];


※Jsonデータの詳細は以下サイトに詳しく書かれています。
 http://hakuhin.jp/js/json.html

(2)線データ(ステップライン)の作成
idは、HTMLファイルdivタグ要素とします。
idにsvg要素を追加します。
widthは幅、marginは余白、heightは高さを表します。
svg要素を作成して、g要素を追加します。

                var svg = d3.select(id).append("svg")
                    .attr({
                        width: width,
                        height: height
                    })
                    .append("g")
                    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

taransformは位置を指定します。

円弧を定義します。
            var pie = d3.layout.pie()
                .sort(null)
                .value(function (d: any) { return d.value; });


円弧の外径と内径を定義します。
            var arc = d3.svg.arc()
                .outerRadius(radius - 10)
                .innerRadius(0);


データバインドして、円弧を作成します。
classはarcとして、CSSファイルにarcの属性定義を行います。
g要素に円弧要素(arc)を設定します。

            var g = this.svg.selectAll("path")
                .data(pie(datas))
                .enter()
                .append("g")
                .attr("class", "arc");





            g.append("path")
                .attr("d", arc);


colorArrに円弧色を定義して、g要素に色を設定します。
colorArr.push("#00000"); などとして、円弧分設定します。

            g.attr("stroke", "black")   
                .style({
                    fill: function (d, i) {
                        return colorArr[i];
                    }
                });


svg要素に円弧アニメーション定義します。
svgにdataを使って円弧要素を作成します。
2秒で透過アニメーションを設定します。(transiton,durationを使用する)

                this.svg.selectAll("path")
                    .transition()   // トランジション開始
                    .duration(2000) // 1秒間でアニメーションさせる
                    .attrTween("d", function (d) {    // 指定した範囲で値を変化させアニメーションさせる
                        var interpolate = d3.interpolate(
                            { startAngle: 0, endAngle: 0 },   // 各円グラフの開始角度
                            { startAngle: d.startAngle, endAngle: d.endAngle }    // 各円グラフの終了角度
                        );
                        return function (t) {
                            return arc(interpolate(t)); // 時間に応じて処理
                        };
                    });


(3) 円弧にデータ表示
円弧にデータ(テキスト)させます。
尚、データ10以下は表示させないようにします。
            g.append("text")
                .attr("transform", function (d: any) { return "translate(" + D3Chart.arc.centroid(d) + ")"; })
                .attr("font-size", "10")
                .attr("font-family", "sans-serif")
                .style("text-anchor", "middle")
                .style("fill", "#ffffff")
                .text(function (d: any) { if (d.data.value < 10) return ""; return d.data.value; });


(4) 情報表示 


on("mouseover")で、円弧をbrawon色にして、infoクラス定義したg要素を表示させて、
そのg要素に情報表示させます。

var mousePos = d3.mouse(this);
にて、円弧の位置が取得できますので、情報g要素をその位置に表示させます。

on("mouseout")で表示した情報g要素を非表示させます。

            this.svg.selectAll("path")
                .on("mouseover", function (d, i) {
                    d3.select(this).attr("style", "cursor:pointer");
                    d3.select(this).attr("style", "fill:brown");
                    var lab = datas[i].label;
                    var val = datas[i].value + "%";
                    var pie = d3.select(id).select("svg");
                    var info = pie.append("g")
                        .attr("class", "info")
                        .attr("x", 0)
                        .attr("width", 70)
                        .attr("height", 62)
                        .style("fill", function (d) {
                            return d;
                        });
                    var width = d3.select(id).select("svg").attr("width");
                    var height = d3.select(id).select("svg").attr("height");
                    var mousePos = d3.mouse(this);
                    var info_x = mousePos[0] ;
                    var info_y = mousePos[1];
                    info.append("rect")
                        .attr("x", info_x)
                        .attr("y", info_y)
                        .attr("width", 100)
                        .attr("height", 50)
                        .attr("stroke", "black")
                        .attr("fill", "white");
                    info.append("text")
                        .attr("x", info_x +5)
                        .attr("y", info_y +20 )
                        .attr("font-family", "selif")
                        .style("fill", "black")
                        .text(lab);
                    info.append("text")
                        .attr("x", info_x +5)
                        .attr("y", info_y + 40 )
                        .attr("font-family", "selif")
                        .style("fill", "black")
                        .text(val);
                })
                .on("mouseout", function (d, i) {
                    var color = colorArr[i];
                    var pie = d3.select(id).select("svg");
                    d3.select(this).attr("style", "fill:" + color);
                    pie.select('g.info').remove();   
                });



(4) 凡例作成
円弧データ説明(凡例)を作成します。
            var legend = this.svg.selectAll(".legend")
                .data(colorArr)
                .enter().append("g")
                .attr("class", "legend")
                .attr("transform", function (d, i) {
                    return "translate(120," + i * 20 + ")";
                });


凡例の色を描画します。
            legend.append("rect")
                .attr("x", 0)
                .attr("width", 18)
                .attr("height", 18)
                .style("fill", function (d) {
                    return d;
                });


凡例の説明を描画します。
            legend.append("text")
                .attr("x", 20)
                .attr("y", 9)
                .attr("dy", ".35em")  // width
                .attr("font-family", "selif")
                .style("text-anchor", "start")
                .style("fill", "#ffffff")
                .text(function (d, i) {
                    return datas[i].label;
                });


0 件のコメント:

コメントを投稿