javascriptアイコン  JavaScript のデータの可視化 (ビジュアライゼーション) のためのライブラリとして D3.js があります。

可視化というと良く分からないかもしれませんが、データは集めただけでは読みにくいですが、そのデータに合わせてグラフ化などをすると非常に分かりやすくなります。

この D3.js は、その手助けをしてくれるライブラリという訳です。
HTML や CSS 、 SVG で描画処理を行います。

IE 8 以前は SVG が対応していないために、上手く機能しない可能性があります。

また、 D3.js を利用するには、 HTML 、 CSS 、 JavaScript 、 SVG についてある程度知っている必要があります。
( SVG についてはこの記事でも軽く触れますが、他については特に説明はしません。 )

この D3.js は他のライブラリのように手軽にグラフやチャートが書けるというものではなく、自分で描画処理を記述する分敷居は高くなりますが、その分、様々なデータ視覚化を可能とします。






D3.jsの紹介


どういう事が出来るのかは、 github の Gallery作者のページが参考になります。

眺めてみるだけでも色々と出来そうで面白いと思います。

このブログでは、グラフというと以前に「Google Chart Toolsを用いたグラフの作成 (円グラフ)」という記事で、円グラフの作成の仕方について紹介しました。

Google Chart Toolsは手軽にグラフの作成が行えますが、この方法ではオンライン上でなければ利用できません。

D3 .js ならば JavaScript ファイルでダウンロードでき、オフライン環境でも利用する事が可能となっております。

(ブラウザや利用する機能によっては、ローカル環境で実行する場合でもローカルサーバーを立ち上げた方が良い場合もあります。このブログでも「enchant.jsを用いたゲーム制作のためのローカル環境での開発の準備」という記事で、 XAMPP を用いたローカルサーバーの立ち上げ方を紹介しております。もし、ローカルサーバーの立ち上げ方が分からない場合は、そちらを参照してください。)

D3.jsの導入
D3.js は、 Mike Bostock が作成したライブラリで、公式サイトからダウンロードできます。

基本英語ですが、日本語化したサイトも用意されておりますので、英語が苦手な人はそちらのドキュメントなどを参考にすると良いです。

ここでは英語の公式サイトからダウンロードする説明をします。

D3-1
D3.js の公式サイト

公式サイトへ行きページの下を見ると、「Download the latest version here :」と書かれており、そのすぐ下にリンクがあります。

それをクリックするとzipファイルをダウンロードできます。

「d3.v3.js」と「d3.v3.min.js」というファイル、それと「LICENSE」というライセンスについて書かれたファイルが含まれます。

開発者向けには「d3.v3.js」を利用し、「d3.v3.min.js」はコードを圧縮して容量を小さくしたもので、公開する場合には「d3.v3.min.js」を利用した方が良いです。

サーバー上で利用する場合は、「d3.v3.min.js」ファイルをアップロードし、HTMLファイルのhead内に、次のコードを記述します。
( head 内ではなく body の最後に実行するスクリプトとともにセットする場合も多いようです。 )

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

もし、わざわざアップロードして利用するのは面倒だという場合は、次のコードをHTMLファイルのhead内に記述する事でも利用する事が可能です。

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

オープンソースで Github にもソースが公開されてますので、最新のバージョンを使いたい場合は、そちらからダウンロードする事が出来ます。

単一の要素を指定する方法
D3.js の使い方について学習します。

まずは、何もライブラリを用いない JavaScript での空の body タグ内に要素を追加して「こんにちは」と表示させる方法についてです。

下のように JavaScript を記述します。

var div = document.createElement("div");
div.innerHTML = "こんにちは"
document.body.appendChild(div);

これを空のbody要素内で読み込むと次のようになります。

D3-2
空のbody要素内にdiv要素を追加して文字を表示した

HTMLファイル全体を見ると、次のように指定しました。

<!DOCTYPE html>
<html lang="ja">
<head>
    <title>テスト</title>
    <meta charset="utf-8" />
</head>
<body>
    <script type="text/javascript">
    var div = document.createElement("div");
    div.innerHTML = "こんにちは"
    document.body.appendChild(div);
    </script>
</body>
</html>

先ほどと同じ事を D3.js で記述すると次のようになります。

var body = d3.select("body");
var div = body.append("div");
div.html("こんにちは");

最初の行のd3.select は、単一の要素を指定します。

また、操作対象の事を「セレクション」と呼びます。

セレクションは CSS の記述と同じようにセレクタが扱えます。
要素名だけではなく、指定したクラスや ID も利用できます。

2 行目では body 要素内に div 要素を追加し、3 行目で div 要素にメッセージを表示します。

複数の要素を指定する方法
単一の要素を指定する場合は select を用いますが、複数の要素を指定する場合は selectAll を用います。

例えば、 body 要素内に次のように記述します。
JavaScript コードは何も書きません。

<div>1行目</div>
<div>2行目</div>
<div>3行目</div>

次のように表示されます。

D3-3
単純に文字が表示される

続いて、 select を用いてメッセージを変更してみます。

次のコードを body タグ内の最後に記述して下さい。

外部ファイルで読み込んだり、bodyタグ内の最初に記述すると上手く行かない可能性があります。

<script type="text/javascript">
var div = d3.select("div");
div.html("こんにちは");
</script>

すると次のように最初のdiv要素のみが変更されております。

D3-4
selectで最初のdiv要素のみが変わる

続いて、 selectAll を用いてみます。

<script type="text/javascript">
var div = d3.selectAll("div");
div.html("こんにちは");
</script>

下の画像のように、全てのdiv要素の文字が変わります。

D3-5
selectAllですべてのdiv要素の文章が変わる

チェインメソッドについて
先ほどの例では、「var div = d3.selectAll("div");」や「div.html("こんにちは");」と分けてコードを記述しましたが、「 . 」 (ピリオド) でつなぐ事で、わざわざ行分けしないでも指定する事が出来ます。

例えば、先ほどのコードは次のように指定しました。

var div = d3.selectAll("div");
div.html("こんにちは");

これを一纏めに記述すると次のように出来ます。


d3.selectAll("div").html("こんにちは");

各操作がセクションを返すために、このように連結して処理を記述出来ます。

例えば、CSSを指定したい場合は、 style を用いて次のようにします。

d3.select("body").style("background-color", "black").style("color", "white");

読み込むと背景色を黒、文字の色を白にします。

D3-6
body要素にCSSが適用されている

必須ではないのですが、連結する場合は推奨される決まりごとがあります。

見やすくするために、それぞれの処理は改行し、その処理を行うセレクションと処理を行い返されたセレクションが同じである場合は、スペースを4つ、処理によってセレクションが変更される場合はスペースを2つ入れてインデントする事が勧められております。

例えば、先ほどの例では次のようになります。

d3.select("body")
    .style("background-color", "black") /* スペース4つ */
    .style("color", "white"); /* スペース4つ */

それに対し、 append を指定した場合は、スペースは二つとなります。

例えば、次のように記述します。

d3.select("body")
  .append("div") /* 新しいセレクションを返すのでスペース2つ */
    .style("color", "white") /* 同じセレクションを返すのでスペース4つ */
  .append("p")
    .html("テスト");

このように、簡潔にコードを記述する事が出来ます。


D3.js を用いた棒グラフの作成


それでは D3.js を用いて棒グラフを作成してみます。

まずは、HTMLとCSSのみで棒グラフを作成し、それに D3.js を用いていきます。

CSSで棒グラフを表現する
D3.js を利用して棒グラフを表現する前に、HTMLとCSSで棒グラフを表現してみます。

D3-7
HTMLとCSSによる簡単な棒グラフ

上の画像のように表示するために、次のようにHTMLファイルでは指定しております。

<!DOCTYPE html>
<html lang="ja">
<head>
<title>テスト2</title>

<meta charset="utf-8" />

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

<style type="text/css">
.bar div {
background-color: rgb(200, 220, 255); /* 棒グラフの色 */
color: #000; /* 文字の色 */
text-align: right;
padding: 5px;
margin: 1px;
}
</style>

</head>
<body>

<!-- 棒グラフの描画 -->
<div class="bar">
    <div style="width: 50px;">10</div>
    <div style="width: 25px;">5</div>
    <div style="width: 125px">25</div>
    <div style="width: 65px">13</div>
</div>

</body>

正直、データの数が少ないうちはそれほど手間にはなりませんが、データの数が増えると手間が掛かるためにあまり効率的ではありません。

そこで、 D3.js を用いる事でグラフの作成をもう少し効率的に行えます。

D3.js を用いた棒グラフの作成
先ほどのCSSとHTMLを用いたdiv要素で作ったグラフをベースに見ていきます。

body要素内には、次のHTMLのみが記述します。

<div class="bar"></div>

続いて、 D3.js を用いて JavaScript のコードを書いていきます。

まず、クラス名「bar」の要素を取得します。

クラス名を指定する場合は先頭に「 . 」 (ピリオド) を付けます。

var bar = d3.select(".bar");

次に、 selectAll を用いますが、「bar」というクラス名を付けたdiv要素しか記述していないために、 selectAll の対象はありません。

var div = bar.selectAll("div");

さらに、 data を用います。

これは、配列を指定する事で DOM 要素とデータを結び付けます。

上の場合は、先ほどの selectAll で div 要素を指定しましたが、それとデータの配列が結びつきます。

配列の最初のデータは、指定されたセレクションの最初と結び付き、配列の二番目のデータは、指定されたセレクションの2番目と結び付き、それが配列の数だけ繰り返されます。

var d = [10, 5, 25, 13];

var barData = div.data(d);

上のコードの場合は、 selectAll("div") で指定した div 要素と配列のデータが結び付きます。

ただ、 data で指定する時の DOM 要素は空です。データは4つあるのに数があっていません。

そこで用いるのが enter です。

これは、データの数がDOM要素よりも多い場合に、余ったデータをセレクションとして返します。

そこで append を用いることで、不足しているdiv要素を追加します。

var dd = barData.enter().append("div");

なお、ここの例ではデータの数がDOM要素よりも多かったのですが、逆にDOM要素の数がデータの数よりも多い場合は、 exit を用います。

data を用いる場合は、次の三つのセレクションに分けられます。

1. update - DOM 要素とデータの配列が結び付いている状態

2. enter - データの数が DOM 要素よりも多い状態

3. exit - データの数が DOM 要素よりも少ない状態

update を利用する場合は、 data を指定すると自動的に返り値として戻ってくるので enter や exit のようにその後に追加で指定する必要はありません。

話を元に戻して次に進めます。

続いて、 HTML と CSS のみでグラフを作成した時には、 style 属性で width プロパティの値を指定しておりましたが、それと同じ事を D3.js で行います。

style を用いて次のようにします。

dd.style("width", function (d) {
    return d * 5 + "px";
});

style に指定する値は、直接入力しなくても、このように関数を用いる事が出来ます。

この場合、引数の 「d」 は、配列で用意したデータと結び付いております。
「d」という名前は自分の好きなように変える事が出来ますが、「d」と記述する場合が多いようです。

最後に、 text を用いる事で、グラフに表示する文字を指定します。

dd.text(function (d) {
    return d;
});

この場合の引数の 「d」 もデータの事を指します。

これらを一纏めにすると、次のように記述出来ます。

// 配列でまとめたデータ
var d = [10, 5, 25, 13];

d3.select(".bar")
  .selectAll("div")
    .data(d)
  .enter().append("div")
    .style("width", function (d) { return d * 5 + "px"; })
    .text(function (d) { return d; });

この程度の作業だと面倒だと感じたかもしれませんが、これならデータを追加するのも簡単で、配列にデータの数値を追加するだけで新しいデータを追加できます。

HTMLとCSSのみでは、div要素を追加し直さなくてはなりません。

D3-8
配列を変更するだけでデータを追加できる

最終的な HTML ファイルは次の通りです。

<!doctype html>
<html lang="ja">
<head>
<title>テスト3</title>

<meta charset="utf-8" />

<style type="text/css">
.bar div {
background-color: rgb(200, 220, 255);
color: #000;
text-align: right;
padding: 5px;
margin: 1px;
}
</style>

</head>
<body>

<div class="bar"></div>

<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script type="text/javascript">
var d = [10, 5, 25, 13, 34, 21];

d3.select(".bar")
  .selectAll("div")
    .data(d)
  .enter().append("div")
    .style("width", function (d) { return d * 5 + "px"; })
    .text(function (d) { return d; });
</script>

</body>
</html>

スケールの設定
グラフの作成は出来ましたが、先ほどの 「.style("width", function (d) { return d * 5 + "px"; })」という部分は、5 という数字が何を表しているのかが一目見て分かりづらいです。

このように、コード中に出てくる数値は、コードが単純であったり、制作中の場合はすぐに分かりますが、第3者が見ると分かりづらく、マジックナンバーと呼ばれ、あまり良い表現ではありません。

そこでスケールを設定する事で、もう少し分かりやすくします。

ここではリニアスケールを用います。

d3.linear でリニアスケールを用いるようにします。

リニアスケールは「y = ax + b」の直線の式に合うように、入力値である x と、出力である y を指定する事で、自動的にそれに合わせた値を返すようになります。

直線の式の x に当たるのは、 domain で入力するデータの範囲を指定します。指定する時は配列を用いて、少なくとも2つ以上指定する必要があります。 今回は用いませんが、引数に何も指定しないと現在の入力のための範囲を返します。

さらに直線の式の y に当たるのは、 range で実際に表示する出力の範囲を指定します。これも範囲を指定する時には、配列を用いて少なくとも2つ以上を指定する必要があります。こちらも引数を指定しないと現在の出力範囲を返します。

もし、 domain と range の配列の数が一致しない場合は、少ない方に自動的に合うようになります。

先ほどの例だと、一番大きい数値は「34」となります。

そして範囲は、「数値 × 5」となっており、最大で 170 px となります。

それをそれぞれ設定すると、次のようになります。

var graph = d3.scale.linear()
    .domain([0, d3.max(d)]) /* d は配列でd3.maxで、その最大値つまり34となります */
    .range([0, 170]);

このように指定すると、変数 graph は自動的に「y = ax + b」の直線式として判別してくれる関数がセットされます。

この例だと、式は y = 5x となり、例えば、 graph(6) とすると 30 が返ってきます。

後は、用意した関数を先ほどのコードに用います。

.style("width", function (d) { return graph(d) + "px"; })
d3.scale.linear に domain や range を指定しないと、それぞれ [0, 1] を指定したのと同じ状態になります。

そのため、例えば 「linear(0.3)」 と指定した場合は、そのまま「0.3」が返ってきます。

また、数値以外にも利用できます。

今回は用いませんが、次のようにする事も出来ます。

var color = d3.scale.linear()
    .domain([-255, 0, 255])
    .range(["red", "green", "blue"])

これを利用し、 color(128) などと入力すると rgb値を返すようにも出来ます。

SVG を用いたグラフの描画


先ほどはCSSを用いてグラフの作成をしましたが、この方法では柔軟性があまりありません。

SVG ( Scalable Vector Graphics ) を用いると描画処理に表現の幅が広がり、ベクター画像であるために、拡大したり縮小しても画像が汚くなってしまう事も無く綺麗に描画する事が出来ます。

SVG は、登場してからかなり経ちますが、ブラウザでは IE 8 までは対応していなかったのであまり注目されておりませんでした。

しかし、IE 9 からは対応するようになったために、ブラウザ上でも注目を集めるようになりました。

SVG はブラウザだけではなく、Adobe Illustrator などのソフトでも用いられており、 Illustrator で描画した図形を利用するという事も可能です。

SVG を利用する場合はHTMLファイルの先頭に次のDOCTYPE宣言を入れる必要があります。

<!DOCTYPE html>

SVG の使い方
SVG の使い方について説明をします。

まずは、次のコードを記述し、文字コードを UTF-8 として、拡張子を「.svg」にして保存してください。
( 文字コードを変更するには、例えば、メモ帳の場合は保存時に「文字コード」とあるのでそこを変更します。変更しないと ANSI となります。 )

<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <circle cx="150" cy="200" r="100" fill="rgb(255, 0, 0)" />
  <rect x="100" y="350" width="200" height="200" fill="#0F0" />
</svg>

はじめてみると、色々と難しそうに見えるかもしれませんが、まず svg タグについて見ると、これは定型文なので難しく考えずにそのまま覚えてしまって下さい。

長ったらしいので、コピペするのが楽です。

続いて、svg タグ内の circle タグは円の描画、rect タグは矩形の描画で、各属性は位置や大きさ、描画色などを指定しております。

保存したら、ブラウザで開いてみて下さい。

SVG に対応していれば次のように表示されます。

D3-9
SVG による図形の描画

HTML ファイルで外部の SVG ファイルを利用する方法
続いて、 HTML ファイルで SVG を用いる方法について説明します。

4つの方法があるので順番に説明します。

まずは、 object タグを用いる方法です。

この方法は HTML ファイルに次のように object タグを記述します。

head タグ内に記述すると IE 9 では読み込めません。body タグ内に記述して下さい。

<object type="image/svg+xml" data="svgファイルのURL" ></object>

先ほどの svg ファイルを読み込むと下のように表示されます。

D3-10
object タグで svg ファイルを読み込んだ

このままだと一部しか表示されないので、 width や height で svg の大きさを指定するよう書き換えます。

<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     width="400" height="600">
  <circle cx="150" cy="200" r="100" fill="rgb(255, 0, 0)" />
  <rect x="100" y="350" width="200" height="200" fill="#0F0" />
</svg>

これできちんと画像が表示されます。

img タグを用いて SVG 表示する
二つの方法は img タグで SVG ファイルのパスを指定する方法です。

<img src="SVGファイルのURL" />

これは単純なので特に説明は不要かと思います。

CSS を用いて SVG を表示する
三つ目の方法は CSS を用いて指定します。

例えば次のようにします。

<style type="text/css">
.svgtest {
    background: url(test.svg);
    width: 400px;
    height: 600px;
}
</style>
<div class="svgtest"></div>

この方法では、 CSS で width と height を指定しているので svg タグの属性に指定する必要はありません。

HTML に直接 SVG を埋め込む
四つ目の方法はHTMLに直接 SVG を記述します。

これは単純に svg タグを body 要素内に記述するだけです。

SVG でグラフを描画する
それでは SVG のHTMLファイルへの埋め込み方が分かったところで、先ほどのグラフを SVG を用いて描画してみます。

まずは、 CSS を次のように指定します。

.bar rect {
    fill: rgb(200, 220, 255); /* グラフ用の描画色 */
}

.bar text {
    fill : #000; /* グラフの文字用の描画色 */
    text-anchor: end; /* textタグの x や y 座標の設定を文字の右端に指定 */
}

若干、 SVG を用いなかった時の CSS とプロパティとは異なりますが、ほとんど同じです。

続いて SVG を記述します。

<svg class="bar" width="170" height="160" xmlns="http://www.w3.org/2000/svg">
    <g transform="translate(0,0)">
        <rect width="50" height="25"></rect>
        <text x="45" y="17.5">10</text>
    </g>
    <g transform="translate(0,26)">
        <rect width="25" height="25"></rect>
        <text x="20" y="17.5" >5</text>
    </g>
    <g transform="translate(0,52)">
        <rect width="125" height="25"></rect>
        <text x="120" y="17.5">25</text>
    </g>
    <g transform="translate(0,78)">
        <rect width="65" height="25"></rect>
        <text x="60" y="17.5">13</text>
    </g>
    <g transform="translate(0,104)">
        <rect width="170" height="25"></rect>
        <text x="165" y="17.5">34</text>
    </g>
    <g transform="translate(0,130)">
        <rect width="105" height="25"></rect>
        <text x="105" y="17.5">21</text>
    </g>
</svg>

それぞれのタグについての詳しい説明はここではしませんが、 rect タグで矩形を描画、 text タグで文字の描画、 g タグでそれらをグループ化してレイアウトを調整しております。

D3-11
SVC による棒グラフの作成

D3.js を用いた SVG による棒グラフの作成
先ほどは SVG を用いて直接記述をしましたが、続いて D3.js を用いて棒グラフを作成します。

まずは、HTMLファイルの body タグ内のグラフを用意したい場所に svg タグを用意します。

<svg class="bar"></svg>

続いて、 JavaScript でコードを記述していきます。

CSS の時と基本は同じなので、一気にコードを記述します。

var d = [10, 5, 25, 13, 34, 21];

// グラフの幅と一つの棒の高さ
var width = 170, barHeight = 25;

var graph = d3.scale.linear()
    .domain([0, d3.max(d)])
    .range([0, width]);

var barChart = d3.select(".bar")
    // attr は属性の指定
    .attr("width", width)
    // 棒の高さは barHeight だが、それにグラフ間の隙間として 1 px 加える
    .attr("height", (barHeight + 1) * d.length)

var bar = barChart.selectAll("g")
    .data(d)
  .enter().append("g")
    // 要素の表示位置を変える、中の要素はローカル座標となる
    // 関数の二つ目の引数 i は、 0 から始まるインデックスを返す
    .attr("transform", function(d, i) { return "translate(0," + i * (barHeight + 1) + ")"; });
   
bar.append("rect")
    .attr("width", graph)
    .attr("height", barHeight)
   
bar.append("text")
    // 3 px 分右端から離す
    .attr("x", function(d) { return graph(d) - 3; })
    // y座標の文字の表示位置の調整
    .attr("y", barHeight / 2 + 5)
    .text(function(d) { return d; });

attr で属性とその値を指定します。

また、 g タグの transform プロパティの関数の二つ目の引数は、データの配列のインデックスを返します。

0 から開始されます。

その他は、特に目新しい所は無いと思います。

終わりに


D3.js の導入の仕方について説明し、続いてD3.js を用いた棒グラフの作成について説明をしてきました。

とりあえず、棒グラフは作成できましたが、まだまだ実用的なグラフとは言えません。

棒グラフの作成の話はまだ続けたいのですが、長くなってしまったのでここでいったん終了します。

目次

D3.js 関連の記事 - 目次

参考URL

1. CodeZine より
「D3.js」を使ったデータビジュアライゼーション - http://codezine.jp/article/detail/7459
2. ドットインストール より
D3.js入門 - http://dotinstall.com/lessons/basic_d3js
3. Mike Bostock より
Let's Make a Bar Chart - http://bost.ocks.org/mike/bar/
4. @IT より
10分でわかるSVG 基礎編 - http://www.atmarkit.co.jp/fwcr/design/benkyo/webgraphics02/01.html