2016.01.15 Friday
D3.jsによる折れ線グラフの描画
JUGEMテーマ:JavaScript
今回は折れ線グラフを作ってみます。
このブログではこれまで棒グラフを作ってきましたが、なかには「グラフの基本は折れ線グラフなのに、なんで棒グラフから始めるんだう?」と疑問に思ったかたがおられるかもしれません。その理由は、今回折れ線グラフを作っていくなかで分かってくると思いますが、一言でいうと「棒グラフのほうが簡単!」だからです。
折れ線グラフを作るには、データの (x,y) 座標を線で結ぶ必要があります。SVGで線を描画するにはpathという要素を使うのですが、このpath要素の指定の仕方が、かなりのクセモノなんです。
例えば今回のサンプルプログラムでは、(x,y)=(0,30), (100,100), (200,80), (300,150) という4点を赤色の線で結ぶ折れ線グラフを作成しますが、これをSVGのpath要素として生成するには、
<path d="M50,170L150,100L250,120L350,50" stroke="red" stroke-width="2" fill="none"></path>
という、まるで暗号のような要素を生成しなければなりません。
でもご安心を。D3.jsには (x,y) データをもとにSVGのpath要素を生成するメソッドが、ちゃんと用意されています。今回はこのメソッドについて見てゆきましょう。
まずはサンプルプログラムを示します。
■sample.js
// テストデータ var testData = [ {"x":0, "y":30}, {"x":100, "y":100}, {"x":200, "y":80}, {"x":300, "y":150}]; // 折れ線グラフの描画 var line = d3.svg.line() .x(function(d){return 50+d.x;}) .y(function(d){return 200-d.y;}); d3.select("#MyGraph") .append("path") .attr("d",line(testData)) .attr("stroke","red") .attr("stroke-width",2) .attr("fill","none"); // x軸とy軸の作成 var xScale = d3.scale.linear() .domain([0, 300]) .range([0, 300]); var yScale = d3.scale.linear() .domain([0, 160]) .range([160, 0]); d3.select("#MyGraph") .append("g") .attr("class", "axis") .attr("transform","translate(50,200)") .call(d3.svg.axis() .scale(xScale) .orient("bottom") ); d3.select("#MyGraph") .append("g") .attr("class", "axis") .attr("transform", "translate(50,40)") .call(d3.svg.axis() .scale(yScale) .orient("left") );
今回のポイントは、9行目から18行目の部分です。順を追って見てゆくことにしましょう。
まず9行目こそが今回の主役、d3.svg.line()メソッドです。このメソッドこそ、その後ろのx()およびy()メソッドで指定された (x,y) 座標の数値から、先の暗号のようなパス情報を生成してくれる、ありがたいメソッドなのです。今回のx()メソッドでは、単純にデータのx座標を指定するのではなく、50だけ右にシフトさせた値を指定しています。これは、後からグラフの左側にy軸を生成するためのスペースを確保するためです。次の11行目では、y()メソッドで200からデータのy座標を引いた値を指定していることに注意してください。これは、SVG画像のx,y座標系では、画像のいちばん上がゼロになっていて下にいくほどyの値が増加するような座標系になっているためです。そこで、SVG画像の上辺から200だけ下に行ったところを「折れ線グラフのy=0」として、そこからデータのy座標値分だけ上にデータの点を指定しているのです。
d3.svg.line()メソッドの動作は、ウェブブラウザのデベロッパーツールを使うとよく分かります。デベロッパーツールのJavaScriptコンソールで、2行目から18行目までを入力してみましょう。次に、コンソール上でline(testData)と入力してください。すると、次のような出力が得られます。
"M50,170L150,100L250,120L350,50"
つまりd3.svg.line()メソッドは、(x,y)データ系列をもとに、path要素の例の "暗号部分" (?) を生成してくれているのです。こうして生成したpathメソッドで折れ線を生成しているのが13行目から18行目です。
21行目以降はx軸とy軸を作成しています。ここでy軸のスケールの指定が、数値[0, 160] をSVG画像上における座標系で [160, 0] の範囲にマッピングしている点に注意してください。ちなみに、x軸はorient()メソッドの引数を"bottom"と指定すれば良く (35行目)、y軸は"left"と指定してください (44行目)。
次回は円グラフを作成してみましょう!
