d3.jsはzoomによるグラフの拡大縮小ができます。このとき軸を数値ではなく時間軸として設定していると、自動で軸の表記粒度を変更してくれます。具体的には以下のサンプルグラフを弄ってみてください。マウススクロールで拡縮、ドラッグで移動できると思います。
気付くと思いますが、時間軸の表記が日本では一般的でない表記です(US表記らしい)。私はこれでもわかるのでよいと思うのですが、これでは困るという人がいます。
今回は、この部分を書き換える方法を検討します。実際の描画サンプルまでは提示しません。
使うもの
- d3.time.format.mutil()
- d3.locale()
d3.locale()
d3.locale()で月名や曜日名を再定義します。デフォルトだと完全に英語で扱いづらいです。
var definition = {
"decimal": ".", "thousands": ",", "grouping": [3], "currency": ["$", ""], "dateTime": "%a %b %e %X %Y", "date": "%m/%d/%Y", "time": "%H:%M:%S", "periods": ["AM", "PM"], "days": ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], "shortDays": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], "months": ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], "shortMonths": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] }
%Xな表記はTimeFormattingのページを参照しながら書き換えてください。
あとは通常のtimeFormatと同じ流れで
var format = d3.locale(definition).format("%b %m");
console.log(format(new Date(2016,2,25));
みたいな感じでやれば扱えます。
d3.time.format.multi()
デフォルトだとこんな感じ
var format = d3.time.format.multi([ [".%L", function(d) { return d.getMilliseconds(); }], [":%S", function(d) { return d.getSeconds(); }], ["%I:%M", function(d) { return d.getMinutes(); }], ["%I %p", function(d) { return d.getHours(); }], ["%a %d", function(d) { return d.getDay() && d.getDate() != 1; }], ["%b %d", function(d) { return d.getDate() != 1; }], ["%B", function(d) { return d.getMonth(); }], ["%Y", function() { return true; }] ]);
これが、基本が曜日+日付で日曜日だけ月名+日付な謎表記の原因です。
おそらく
- 一日は月名のみ
- 日曜日は月名+日付
- それ以外は曜日名+日付
- 時間は12時間表記+AM/PM or :分
といった感じになってます。一番粒度が大きい下から順に評価されていく、と考えればよさそうです。
["%a %d", function(d) { return d.getDay() && d.getDate() != 1; }], ["%b %d", function(d) { return d.getDate() != 1; }],
この二行がよくわからないのでjs詳しい人いたら教えていただきたいです。
- ミリ秒
- 秒
- 分
- 時間
- 日付
- 日付(一日?)
- 月名
- 年
を"表記方法"+"使う値"で記述すればよさそうです。表記方法はやっぱりtimeFormatting参照で。
使い方は
var format = d3.time.format.multi(略);
var scale = d3.time.scale();
scale.tickFormat(format);
な感じで使えます。
複合
time.locale()とd3.time.format.multi()を複合して使います。ドキュメントの関数一覧に見つからないんですが、よく見るとd3.time.format.multi()の最後にちょこっと書いてあります。
The multi method is available on any d3.time.format constructor. For example,d3.time.format.utc.multi returns a multi-resolution UTC time format, and locale.timeFormat.multi returns a multi-resolution time format for the specified locale.
てことで、使い方は以下。
var custom_locale = d3.locale(略);
var format = custom_locale.timeFormat.multi(略);
var scale = d3.time.scale();
scale.tickFormat(format);
感想
そもそもd3自体が難解であることもありますが、こいつにたどり着くのは大変でした。ぐぐっても見つからないしサンプルにもない...表記的にLocalizationにたどり着けば読めばわかるじゃんってことなんでしょうね。
あと手軽にそこそこきれいなグラフが書けると評判なnvd3は、日付をUNIX秒に直して渡すことになっているので、localizationはできますが、multiはできないようです。死ね。やれた人がいたら教えてください。切望しています。
参考文献
↓TimeFormatting
↓Localization
インタラクティブ・データビジュアライゼーション ―D3.jsによるデータの可視化
- 作者: Scott Murray,長尾高弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2014/02/19
- メディア: 大型本
- この商品を含むブログ (3件) を見る