D3とは、 Data-Driven Documents(データ・ドリブン・ドキュメント)のことです。 データからドキュメントを生成するためのライブラリです。 ここで言うデータというのは、グラフなどのもとになる数値のことで、それをグラフィカルな表示にします。 HTMLの表を作成したり、インタラクティブなSVGのグラフを作成し、ユーザーの操作でスムーズに変化させることができます。

グラフには色々な種類があるけれど

D3.jsは頑張れば、複雑なグラフを描けます。 D3公式サイト 「頑張れば」というのが曲者で、グラフを描ける他のライブラリとは違い、グラフを簡単に表示する機能はありません。 D3の機能を利用して、自分でグラフの見た目を作らなくてはいけません。 その分、自由度が高いのですが、それなりに頑張りが必要なわけです。

とにかく手を動かして、円グラフを作ってみた

特に理由はありませんが、円グラフを作ってみました。 ボタンを2つ置いて、データを入れ替えると、円グラフをアニメーションさせようと思います。 デモはここから

D3のライブラリを読み込み

まずは、D3.jsを読み込まないと始まりません。 公式サイトからダウンロードしても良いですし、公式サイトからリンクしても良いでしょう。 今回は、headタグ内に、リンクさせました。

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

円グラフを表示させるdivと、切り替えるボタンを置く

body内はこんな感じにします。 script.jsというファイルにガリガリとD3を書いていこうと思います。 </body>の前ならhtmlの読み込みを気にしなくて良いので、ここに書きます。 その他、円グラフを配置するdivと、ボタンを置いておきます。

    <body>
        <div id="chart"></div>
        <div>
            <input type="button" value="データ1" id="btn1" />
            <input type="button" value="データ2" id="btn2" />
        </div>
        <script src="script.js"></script>
    </body>

script.jsを書く

それでは、ここからは、D3.jsでコーディングをしていきます。 補足として、ソースに書いたコメントも載せていきます。

データの用意

まずは、適当にデータを用意します。 入れ替えようのデータも準備します。

// なにかしらのデータを用意
var dataset1 = [53245, 28479, 19697, 24037, 40245];
// アニメーション用にもうひとつ用意
var dataset2 = [500, 500, 200, 500, 10];

大きさを決める

SVGで円グラフを描画するので、大きさなどを決めます。 自分で色を決めるのだ面倒だったので、d3.scale.category10で、色を用意します。

// SVGの横幅
var width = 640;

// SVGの縦幅
var height = 480;

// 円の大きさ
var radius = Math.min(width, height) / 2 - 10;

// 外側の円の大きさ
var outerRadius = radius - 10;

// 内側の円の大きさ。
// 穴をあけるときは数値を設定。0にすると穴はあかない。
var innerRadius = radius - 50;

// 色を10色用意する関数。色は下記の通り。
// #1f77b4 #ff7f0e #2ca02c #d62728 #9467bd
// #8c564b #e377c2 #7f7f7f #bcbd22 #17becf
var color = d3.scale.category10();

円を生成

円グラフを作成する場合、こう書くのが決まりごとのようです。

// 円を生成します。
// sortにnullを与えると、データの順番通りに円グラフを作成します。
// 指定しない場合は、値の大きい順になります。
// D3.jsでは関数のが引数にデータが入ります。
var pie = d3.layout.pie().value(function(d) {
    return d;
}).sort(null);

// 円の大きさの設定を適用します。
var arc = d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius);

SVGの作成

上記の設定をもとにSVGを描画していきます。 D3.jsは、jQueryのようなチェーンメソッドを採用しています。

// SVG作成
// selectでhtmlのタグ/class/idなどで選択します。
var svg = d3.select("#chart")

// appnedでsvgタグを追加します。
.append("svg")

// attrでタグの属性を設定します。
.attr("width", width).attr("height", height)

// appendでsvgのgタグ(グループ要素)を追加します。
// svg内で描画すると、いくつもタグができるので、まとめて動かすときに便利です。
.append("g")

// 描画場所をsvgの中央にします。
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

// 使いまわしたいので、ここで切ります。
// 描画するだけなら続けて描いても同じです。

グループの作成とデータの読み込み

dataで円としてデータを読み込みます。 そうすると、データがsvgのタグと関連付けされ、enterappendでデータ分だけタグが増えます。 dataset1の中には5つデータがあるので、gタグは5つ追加されます。

var g = svg

// 円はpathというタグで描画されるので、selectAllでまとめてタグを選択します。
.selectAll("path")

// dataでデータを設定します
// 円グラフの場合は、事前に準備したpieを利用しないといけません。
.data(pie(dataset1))

// 要素を自動で増やす時は、enterを使用します。
.enter()

//文字と一緒に円を扱いたいので、gを追加します。
// dataとenterがあるので、データの分だけ自動で増えます。
.append("g");

// 円と文字を個別に設定するので、切ります。

円の描画

増やしたgタグ内に、円を描くときに使用するpathタグを追加します。

//円を描画します。
g

// 円を描くpathを追加します。
.append("path")

// fillはsvgの塗りの属性です。
// 関数で設定するとdataとindexを使えるので、事前に用意したcolorから
// indexで色を取り出して設定します。
.attr("fill", function(d, i) {
    return color(i);
})

// d属性でpathをどう描くか決めます。
// 事前に用意したarcで円を設定できるので、それを入れます。
.attr("d", arc)

// 今の数値を保存します。
.each(function(d) {
    this._current = d;
});

文字の描画

円と同じようにデータの数値を文字としても表示してみます。 SVGにはtextというタグで文字が書けます。

//文字を描画します。
g

// 文字をを描くtextを追加します。
.append("text")

// 文字の位置を円の要素の中心にします。
.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })

// 文字の大きさを設定します。
.attr("font-size", "30")

// 文字の開始位置をセンターにします。
.style("text-anchor", "middle")

//文字の内容を入れます。
.text(function(d) { return d.data; })

//eachで今の数値を保存します。
.each(function(d) {
    this._current = d;
});

イベントの追加

二つのボタンに、クリックでデータが変更するように、イベントを入れます。

//#btnにclickイベントを追加します。
d3.select("#btn1").on("click",function (){arcAnime(dataset1);} , false);
d3.select("#btn2").on("click",function (){arcAnime(dataset2);} , false);

イベントの内容

arcAnimeでは、データを入れ替えて、円と文字にアニメーションを加えています。

//clickイベントの関数を記述します。
function arcAnime(newdata) {
    svg
    .selectAll("path")
    // 新しいデータを設定します。
    .data(pie(newdata))
    // トランジションを設定するとアニメーションさせることができます。
    .transition()
    // アニメーションの秒数を設定します。
    .duration(800)
    // アニメーションの間の数値を補完します。
    .attrTween("d", function(d) {
        var interpolate = d3.interpolate(this._current, d);
        this._current = interpolate(0);
        return function(t) {
            return arc(interpolate(t));
        };
    });

    svg
    .selectAll("text")
    // 新しいデータを設定します。
    .data(pie(newdata))
    //文字を更新します。
    .text(function(d) { return d.data; })
    // トランジションを設定。
    .transition()
     // アニメーションの秒数を設定。
    .duration(800)
    // アニメーションの間の数値を補完。
    .attrTween("transform", function(d) {
        var interpolate = d3.interpolate(arc.centroid(this._current), arc.centroid(d));
        this._current = d;
        return function(t) {
                return "translate(" + interpolate(t) + ")";
        };
    });

}

まとめ

D3.jsは、難しそうなリッチなデータ表示を、比較的簡単に作ることができるのが魅力です。 少し学習コストは高いですが、オリジナルにこだわりたい方は、勉強するのも良いのではないでしょうか。