このメモの狙い
複数ステップでの物やエネルギーの流れを表現するサンキー図を d3-sankey-diagram ライブラリで描きました1 が、この流れの時系列変化をアニメーションで表現するコードを調べたので、まとめておきます。
使用したライブラリー
完成品
データの準備
ここでは「データ総合エネルギー統計」(エネルギーバランス表)を 2006 年から2016 年まで、1 年おきにダウンロードして、データを抽出しました。
(追加で計算した内容は、生成された電力の利用先の割り付けです。企業・事業所他で消費する電力の起源を、事業用発電の一部と自家用発電の全部に割り付けました。)
各年度のフロー量を配列として、JSON 形式のデータにしました。
{
"nodes": [ {(略)}],
"links": [
{"source": "1hp", "target": "3pg", "type": "3",
"value": ["699", "603", "575", "516", "562", "633"]},
{"source": "1ru", "target": "3pg", "type": "3",
"value": ["0", "0", "6", "7", "7", "114"]},
...], }
グラフを更新する部分のコード
update という関数の中に、図を更新する部分を書きます。リンクの数値を SVG のテキストとして置いている部分が、細かなコードの積み重ねになっています。これがなければ、かなりシンプルです。
d3.json('ja_energy_history.json', function(energy) {
layout
.linkValue(function (d) {return d.value[idx];})
.rankSets(energy.rankSets)
.ordering(energy.order);
svg
.datum(layout(energy))
.call(diagram.groups(energy.groups));
var linklab = d3.select('svg')
.selectAll('.link')
.append("text")
.attr("x", function(d) {return d.points[0].x;})
.attr("y", function(d) {return d.points[0].y;})
.attr("dx", "1.5em")
.attr("dy", "0.4em")
.text(function(d) { return d.value[idx] > 1000 ? fmt(d.value[idx]) + ' PJ' : ""; });
d3.interval(update, 3000);
function update() {
idx++;
if(idx > 5) idx = 0;
layout(energy);
svg
.transition().duration(1000).ease(d3.easeCubic)
.call(diagram);
linklab
.transition().duration(1000)
.text(function(d) { return d.value[idx] > 1000 ? fmt(d.value[idx]) + ' PJ' : ""; })
.attr("x", function(d) {return d.points[0].x;})
.attr("y", function(d) {return d.points[0].y;})
d3.select('h2').text(energy.year[idx]);
}
});
原子力発電のノードとそこにつながるリンクのラベルは、きちんと消えたり復活したりします。
コード全体は、github に貼りました。
終わりに
現状では、まだ切り貼りを試しながら動かしている状態で、分かったという感覚には至っていません。一応動くコードになったので、それを保存しておくための記事でした。