d3.js advent calendar 12日目

d3 advent calendar 12日目
d3.svg API (2/2)

12日目は、11日目で紹介しきれなかった、.arc(), .chord()を紹介します

d3.svg.arc()

文字通り、円弧を描く(=円弧になるようなPATHを作成する)APIです

実装: 準備

var colors = d3.scale.category20(); /* 色 */
var data = d3.range(1, 10).map(function(d){
return {key: d, value: 0|Math.random() * 100};}); /* データ */
var arc = d3.svg.arc() /* ←コレです! */
.innerRadius(0) /* 内側の半径 */
.outerRadius(30); /* 外側の半径 */
var pie = d3.layout.pie().value(function(d){
return d.value;});
/* 値を円弧の始端角、終端角に変換するlayout 20日目くらいで説明 */

実装: 要素追加

var g = d3.select('#sample_12_1').append('svg').attr('width', 100).attr('height', 100)
.append('g').attr('tranform', 'translate(50, 50)');
g.selectAll('g').data(pie(data))
/* データを角度のデータを持つデータ配列に変換 */
.append('g').append('path').attr('fill', function(d){ return colors(d.value)})
.attr('d', arc);

説明

基本的にPathの軌跡を定義するd属性をarcでセットするところは同じです。ですが、馬鹿正直に計算すると大変なので、20日目くらいから書き出す、d3.layout.pie()というlayoutを利用します。このlayoutでは、データの値に応じて、開始・終端の角度を計算してくれます。また、角度を与えることで、d3.svg.arc()は指定された内側/外側半径のpathの軌跡を生成するという仕組みです

オプション

  • arc.innerRadius(): 内径をセットします
  • arc.outerRadius(): 外径をセットします
  • arc.centroid(): 重心の位置を2要素配列で取得します
    ラベリングなどに便利です

d3.svg.chord()

データの2要素の間を弦のよう表現で結び、2要素間の関係に着目しやすいグラフを作ることができます

作成するときの注意点

.data()で与えるデータとして次を用意できればいいけど実質無理です
d3.layout.chordを使って関係行列から作ってください

{source:{
    index: Number, subindex: Number, value: Number,
    startAngle: Number,  endAngel: Number,
  },target:{
    index: Number, subindex: Number, value: Number,
    startAngle: Number,  endAngel: Number,
  }}

実例

var matrix = d3.range(1, 10).map(function(d){
return d3.range(1, 10).map(function(d2){
return 0|Math.random() * 100;})});
var colors = d3.scale.category20c();
var chord = d3.layout.chord().padding(.05).matrix(matrix);
var g = d3.select('#svg').append('svg').attr('width', 500).attr('height', 500)
.append('g').attr('transform', 'translate(250, 250)')
.selectAll('g').data(chord.chords).enter()
.append('g').append('path').attr('d', d3.svg.chord().radius(200))
.attr('fill', function(d){ return colors(d.target.index);})
.style('opacity', 0.5);