d3_linear


こんな感じのグラフを作成することになった。

今まではHTML5 canvas上で動作するchart.jsを利用していたけど、

Chart.js | Open source HTML5 Charts for your website


今後、複雑なデータ可視化に対応できるようにするために、


d3_js


D3.js(Data-Driven Documents)を利用することにした。

D3.js - Data-Driven Documents


D3.jsに関しては、以前から気になっており、


js_visual

O'Reilly Japan - JavaScriptによるデータビジュアライゼーション入門


オライリーから出版されたデータビジュアライゼーションの本を読んでいたんだけど、

今回久しぶりにD3.jsのページを開いたら、

メジャーバージョンが一つ上がっており(3系から4系へ)、

しかも3系との互換性がないときたもんだ。


新しいバージョンの方が今後何かと良いだろうと本家のマニュアルを読みながら、


d3_linear


このような折れ線グラフを作成してみた。


最初にJavaScriptで書いたコードを載せておく。


<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>
<script>
var dataset = [
	{label:"2016/3", count:26},
	{label:"2016/4", count:26},
	{label:"2016/5", count:45},
	/** 同じようなデータが続く **/
];

var margin = {top : 20, right : 40, bottom : 100, left : 100};
var width = 960 - margin.left - margin.right;
var height = 400 - margin.top - margin.bottom;

// SVGの表示領域を生成
var svg = d3.select("#graph")
		.attr("width", width + margin.left + margin.right)
		.attr("height", height + margin.top + margin.bottom)
		.append("g")
		.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
	
var xdomain = [];
for (var i = 0; i < dataset.length; i++) {
	xdomain.push(dataset[i].label);
}

//x軸は日付の文字列を等間隔に並べる
var xScale = d3.scalePoint()
			.domain(xdomain)
			.range([0, width]);

//x軸は0から最大の値+5になるように指定
var yScale = d3.scaleLinear()
			.domain([0, d3.max(dataset, function(d){ return d.count + 5; })])
			.range([height, 0]);

//枠組み
var xAxis = d3.axisBottom(xScale);
var yAxis = d3.axisLeft(yScale);

var line = d3.line()
		.x(function(d) {return xScale(d.label);})
		.y(function(d) {return yScale(d.count);})
		.curve(d3.curveLinear);

svg.append("g")
	.attr("class", "x axis")
	.attr("transform", "translate(0," + height + ")")
	.call(xAxis);

svg.append("g")
	.attr("class", "y axis")
	.call(yAxis); 
	
svg.append("path")
	.datum(dataset)
	.attr("class", "line")
	.attr("d", line(dataset));
</script>

グラフの描写の装飾に関してはCSSで対応することにした。


<style>
.axis path, .axis line {
	fill: none;
	stroke: black;
}
.tick text {
	font-size: 12px;
}
.x .tick text{
	font-size: 10px;
	transform: rotate(-60deg) translate(-30px, -5px);
}
.line {
	fill: none;
	stroke: blue;
	stroke-width: 2px;
}
</style>

こんな感じ。


<script>の記述の上部にグラフの描写箇所の指定は

<svg id="graph"></svg>

を記述した。


細かい説明は他のサイトを見てもらうとして、

3.X系統から4.X系統の変更点で苦戦した箇所として、


var yScale = d3.scaleLinear()
			.domain([0, d3.max(dataset, function(d){ return d.count + 5; })])
			.range([height, 0]);

scale関連の記述方法で、3.X系統では、


var yScale = d3.scale.linear()
			.domain([0, d3.max(dataset, function(d){ return d.count + 5; })])
			.range([height, 0]);

d3オブジェクト内にscaleオブジェクトがあって、scaleオブジェクト内のlinear()を実行する事で、scaleの設定が出来たけど、

4.X系統ではscaleオブジェクトが廃止になり、d3オブジェクトからscaleLinear()を直接実行することでscaleの設定ができる。

※scaleの設定:軸に表示される数字がグラフのサイズに合わせて均等に配置


y軸のように単純に数字の目盛であればこれで良いけど、

移行の際に最も苦戦した箇所が、


d3_linear_xaxis


x軸のscaleで、見ての通り文字列が均等に並んでいる。

3.X系統では、


var xScale = d3.scale.ordinal()
			.domain(xdomain)
			.rangePoints([0, width]);

scaleオブジェクトのordinal()実行後にrangePoints()で幅指定すれば良かったけど、4.Xではこれがなくなっていて、

var xScale = d3.scalePoint()
			.domain(xdomain)
			.range([0, width]);

d3オブジェクト内のscalePoint()を実行すれば良いみたい。

この機能を見つけるまでに時間がかかった。


他に3.X系統から4.X系統への変更点で影響を受けた箇所といえば、


x軸とy軸の生成時にd3オブジェクト内のsvgオブジェクトを利用していたけど、

svgオブジェクト自体が廃止になったあたりですかね。


var xAxis = d3.axis.svg.axis()
			.scale(xScale)
			.orient("bottom");

のようなコードが


//4.X系統
var xAxis = d3.axisBottom(xScale);

へ変更とか