サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

D3.js入門 05: グラフの棒にラベルを加える


D3.js入門 04: グラフにアニメーションを加える」(以下「D3.js入門 04」)で数値軸と項目軸のついた縦棒グラフに、アニメーションを与えました。グラフの左にはパーセンテージの数値軸がありますので、棒の長さから大きさの見当はつきます。けれど、もっとわかりやすいように、グラフの棒ごとに数値のラベルを添えましょう(サンプル001)。「D3.js入門 03」のコード001「棒グラフを伸びる動きで表示する」を書き改めるかたちで進めます。

サンプル001■D3.js: SVG Bar Chart with Transition and labels


>>画像をクリックでjsdo.itへ

01 グラフの棒に数値のラベルを添える

グラフの棒の<rect>要素は、親(<g>)要素にselection.append()メソッドで加えていました(図001)。さらに、数値のラベルを<text>要素で足すため、親要素をつぎのように変数(bar)に取っておきます。selection.append()メソッドで引数に'text'を渡したら、xy座標を決めて、selection.text()メソッドでデータから取り出した数値を与えます(<text>要素の加え方については「D3.js入門 02: 外部ファイルのデータからSVGで棒グラフを描く」02「D3がつくるSVG要素で棒グラフを描く」参照)。<text>要素のスタイルは以下のように定めました。


d3.tsv('data.tsv', type, function(error, data) {

	// elements.selectAll('.bar')
	var bar = elements.selectAll('.bar')
		.data(data)
		.enter();  // .append('rect')
	bar.append('rect')

	bar.append('text')
		.attr('x', function(d) {
			return getX(d);
		})
		.attr('y', function(d) {
			return getY(d);
		})
		.text(getValue);
});

function getValue(d) {
	return d.value;
}

<style>要素

.chart text {
	font: 10px sans-serif;
}

図001■グラフの棒の<rect>要素が親の<g>要素に加えられている

図001

これでグラフの棒に、それぞれデータの数値がラベルとして加わります(図002)。ただ、100%を1とする小数値なので見づらく、棒は順にアニメーションで伸びるのに数値がはじめからすべて出ているのもバランスに欠けます。

図002■グラフの棒に小数の比率がラベルとして加わった

図002

02 ラベルをパーセンテージの数値にする

ラベルの数値はパーセンテージ、つまり100倍にしましょう。小数点以下は第1位までで切り捨てます。そのための関数(getPercentage())を新たにつぎのように定め、selection.text()メソッドに渡します。小数点以下が0でも「.0」と示すように、数値は文字列に変えました。


d3.tsv('data.tsv', type, function(error, data) {

	bar.append('text')

		.text(getPercentage);  // getValue);
});

function getPercentage(d) {
	var num = Math.floor(d.value * 1000) / 10;
	var num_str = String(num);
	if (Math.floor(num) === num) {
		num_str += '.0';
	}
	return num_str;
}

グラフの領域やラベルの位置やフォントサイズなどを、つぎのように少し調整しましょう。これで、グラフの棒にそれぞれのパーセンテージが小数点以下第1位までラベルで示されます(図003)。


// var margin = {top: 20, right: 20, bottom: 30, left: 30};
var margin = {top: 20, right: 10, bottom: 30, left: 40};

d3.tsv('data.tsv', type, function(error, data) {

	bar.append('text')

		.attr('dx', '-0.2em')
		.attr('dy', '-0.25em')
		.text(getPercentage);
});

<style>要素

.chart text {
	font: 12px /* 10px */ sans-serif;
}

図003■グラフの棒にパーセンテージの数値が示される

図003

03 数値ラベルもアニメーションで示す

数値ラベルにもアニメーションを与えて、グラフの棒と表現を整えます。派手に動かしても目障りなので、透明から不透明にフェードインさせることにしましょう。時間のタイミングは揃えたいので、メソッドtransition.duration()transition.delay()に渡す引数値は、つぎのようにあらかじめ変数(durationとdelay)に与えておきます。そして、数値ラベル(<text>要素)にフェードインのアニメーションを加えました(selection.transition()メソッドの定めについては前出「D3.js入門 04」03「グラフの棒をアニメーションで伸ばす」参照)。これで、グラフの棒に添えた数値ラベルも、ともにアニメーションで表れます。書き改めたスクリプトとスタイルは、以下のコード001にまとめました。


var duration = 500;
var delay = 50;

d3.tsv('data.tsv', type, function(error, data) {

	bar.append('rect')

		.transition()
		.duration(duration)  // 500)
		.delay(function(d, i) {
			return i * delay;  // 50;
		})

	bar.append('text')

		.text(getPercentage)  // ;
		.style('opacity', 0)
		.transition()
		.duration(duration)
		.delay(function(d, i) {
			return i * delay;
		})
		.style('opacity', 1);
});

コード001■棒グラフに数値ラベルを与えてアニメーションさせる


var duration = 500;
var delay = 50;
var chart = d3.select('.chart');
var margin = {top: 20, right: 10, bottom: 30, left: 40};
var width =  +chart.attr('width') - margin.left - margin.right;
var height = +chart.attr('height') - margin.top - margin.bottom;
var x = d3.scaleBand()
	.rangeRound([0, width]).padding(0.1);
var y = d3.scaleLinear()
	.rangeRound([height, 0]);
var elements = chart.append('g')
	.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
d3.tsv('data.tsv', type, function(error, data) {
	x.domain(data.map(getName));
	y.domain([0, d3.max(data, getValue)]);
	elements.append('g')
		.attr('class', 'axis axis--x')
		.attr('transform', 'translate(0,' + height + ')')
		.call(d3.axisBottom(x));
	elements.append('g')
		.attr('class', 'axis axis--y')
		.call(d3.axisLeft(y).ticks(10, '%'));
	var bar = elements.selectAll('.bar')
		.data(data)
		.enter();
	bar.append('rect')
		.attr('class', 'bar')
		.attr('x', function(d) {
			return getX(d);
		})
		.attr('y', height)
		.attr('width', x.bandwidth())
		.transition()
		.duration(duration)
		.delay(function(d, i) {
			return i * delay;
		})
		.ease(d3.easeElasticOut)
		.attr('y', function(d) {
			return getY(d);
		})
		.attr('height', function(d) {
			return height - getY(d);
		});
	bar.append('text')
		.attr('x', function(d) {
			return getX(d);
		})
		.attr('y', function(d) {
			return getY(d);
		})
		.attr('dx', '-0.2em')
		.attr('dy', '-0.25em')
		.text(getPercentage)
		.style('opacity', 0)
		.transition()
		.duration(duration)
		.delay(function(d, i) {
			return i * delay;
		})
		.style('opacity', 1);
});
function type(d) {
	d.value = +d.value;
	return d;
}
function getName(d) {
	return d.name;
}
function getPercentage(d) {
	var num = Math.floor(d.value * 1000) / 10;
	var num_str = String(num);
	if (Math.floor(num) === num) {
		num_str += '.0';
	}
	return num_str;
}
function getValue(d) {
	return d.value;
}
function getX(d) {
	return x(d.name);
}
function getY(d) {
	return y(d.value);
}

<style>要素

.chart rect {
	fill: steelblue;
}
.bar:hover {
	fill: brown;
}
.axis--x path {
	display: none;
}
.chart text {
	font: 12px sans-serif;
}

[*1] アーサー・コナン・ドイル『踊る人形』でシャーロック・ホームズは、この事実から暗号文の「E」をただちに見抜きました。

作成者: 野中文雄
更新日: 2017年3月4日 スクリプトの無駄を1箇所修正。
作成日: 2017年2月23日


Copyright © 2001-2017 Fumio Nonaka.  All rights reserved.