D3.js Force Layoutのノードを画像に変えてみる
前回、前々回とD3.jsのForce Layoutで簡単なネットワークを表現したが、ノードにただのcircleを使っていたので、今回はこれを画像に変えてみた。画像にすることで、ノードの意味をより明確に視覚化することができる。
過去記事:
D3.jsのForce Layout (力学モデルでグラフ描画するレイアウト)を動かしてみた - カタカタブログ
D3.js Force Layoutのパラメータについて調べてみた - カタカタブログ
ノードのグループ化
その前に、簡単なリファクタリングをしておく。今まではSVGで、ノードを表すcircleとtext要素をそれぞれ別々に定義していたが、g要素で囲むことでグループ化でき、そのグループに対して座標移動させるようなコードに変更する。
今までのコード
var node = svg.selectAll("circle") .data(nodes) .enter() .append("circle") .attr({r: 20, opacity: 0.5}) .style({"fill": "red"}) .call(force.drag); var label = svg.selectAll('text') .data(nodes) .enter() .append('text') .attr({"text-anchor":"middle", "fill":"white"}) .style({"font-size":11}) .text(function(d) { return d.label; }); force.on("tick", function() { link.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; }}); node.attr({cx: function(d) { return d.x; }, cy: function(d) { return d.y; }}); label.attr({x: function(d) { return d.x; }, y: function(d) { return d.y; }}); });
グループ化したコード
var g = svg.selectAll("g").data(nodes).enter().append("g”) .call(force.drag); var node = g.append("circle") .attr({r: 20, opacity: 0.5}) .style({"fill": "red"}) var label = g.append("text") .attr({"text-anchor":"middle", "fill":"white"}) .style({"font-size":11}) .text(function(d) { return d.label; }); force.on("tick", function() { link.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; }}); g.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); });
これでノードとラベルの座標を指定するコードに重複がなくなった!この変更前後で表示されるネットワーク図はまったく変わらない。
ノードを画像に
続いて、ノード部分を画像に変えてみる。SVGで画像を表示するためには、imageタグを以下のように使用する。
<image xlink:href="<画像へのパス>" width="75" height="60"></image>
今回、サンプル画像として、以下のサイトからフリーアイコンをSVG形式でダウンロードしたので、それをHTMLファイルが置かれたディレクトリにimagesというディレクトリを作成し、その中に配置した。
http://www.flaticon.com/free-icon/dwelling-house_2144
circle要素のところをimageに置き換え、参照先に入手した画像を指定する。座標はさきほど定義したグループに設定しているので、画像を配置するときに座標は意識しなくてよい。
var g = svg.selectAll("g") .data(nodes) .enter() .append("g") .call(force.drag); var node = g.append("image") .attr({"xlink:href":"images//dwelling1.svg", "width":75, "height":60 }); var label = g.append("text") .attr({"text-anchor":"middle", "fill":"black"}) .style({"font-size":14}) .text(function(d) { return d.label; });
ノードが単純な円だったのが、きれいな画像に変わった!もちろん、今回はローカルの画像を表示したが、パスをURL形式にすればインターネット上の画像表示もできるし、jpenやpng形式の画像も表示できる。
以上!