D3.jsのforce layoutで遊ぶ
前回はtransitionで、ひたすら円を動かし、そして消すをやりました。
今回は、見た目難しそうなアレをやってみます。
force layout
あんなやつです。
作ってみる
データの用意
nodes用のデータ、links用のデータの2つを用意します。
データの例として、
var data = { nodes: [ { name: 'Alice' }, { name: 'Bob' }, { name: 'Eve' } ], links: [ { source: 0, target: 1 }, { source: 0, target: 2 }, { source: 1, target: 2 } ] };
nodesにはAlice、Bob、Eveの3要素。
linksにはnodesのどの要素が、どの要素と繋がりがあるかを表しています。
例のデータだと、
source: 0, target: 1
で、nodesの0番目(Alice)から1番目(Bob)へと繋がるようなイメージ。
Alice → Bob、Alice → Eve、 Bob → Eveと繋がるので、結果は三角形が出来上がります。
このようなデータだと良さ気です。
データを使って、作る
svg要素を作るところはカット。
force、line、circleを作ります。
var force, line, circle; force = d3.layout.force() .nodes(data.nodes) .links(data.links) .size([200, 200]) .linkDistance([100]) .charge([-100]) .start(); line = d3.selectAll('line') .data(data.links) .enter() .style({ // お好みの線の色と太さ }); circle = d3.selectAll('circle') .data(data.nodes) .enter() .attr('r', 20) .call(force.drag);
forceのnodes、linksでデータを指定してやります。
linkDistanceはnodes同士の間隔。
chargeは反発力みたいな。そんな感じです。
正の値を入れると面白い動きをします。
そして、circleの最後のcall(force.drag)
。
これで、マウスドラッグが可能になります。
tick
最後にtickを。
force.on('tick', function () { line.attr({ 'x1': function (d) { return d.source.x; }, 'y1': function (d) { return d.source.y; }, 'x2': function (d) { return d.target.x; }, 'y2': function (d) { return d.target.y; } }); circle.attr({ 'cx': function (d) { return d.x; }, 'cy': function (d) { return d.y; } }); });
これで大体完成となります。
意味なんかはreference読むのが一番かなぁと思っていますが、
きの基本形覚えてしまえば、いろいろ応用が利くはずです。
サンプル
今回もサンプルを作りました。
今回は、TwitterのREST APIから自分のアカウントのフォローしているアカウント一覧を取得。
jsonファイルに落とし込んで、フォローしている人との繋がりを描画しました。
要するに、0が自分で、targetをフォローしているユーザとするだけです。
{ source: 0, target: 1 }, { suurce: 0, target: 2 } // ....
nodeはcircleではなく、imageを使用し、フォローしている方のアイコンを表示しています。
デモはこちら (URL間違ってたから修正w)
※重いので注意
ソースはこちら
最後に
難しそうなものですが、案外やってみると簡単に作れてしまいます。
どちらかというと、データに何を使うか、繋がりをどう表すのかが重要になりそうです。
今度は何をしよう。。。