データバインディング
セレクションに対してデータをバインドします。
以下の例では、リンゴ、オレンジ、バナナというパラグラフに対しApple,Orange,Bananaというデータをバインドし、テキストを更新しています。
<div id="fruits"> <p>リンゴ</p> <p>オレンジ</p> <p>バナナ</p> </div>
var fruits = ["Apple", "Orange", "Banana"];
d3.select("#fruits").selectAll("p")
.data(fruits).text(function(d) {return d;});
データの数とセレクションDOMの数が一致しない場合は、enterとexitメソッドを利用します。
enterは余ったデータをセレクションとして返すので、appendでp要素を追加し、textでデータの内容をp要素に設定します。
var fruits = ["Apple", "Orange", "Banana", "Strawberry"];
d3.select("#fruits").selectAll("p")
.data(fruits).text(function(d) {return d;})
.enter().append('p').text(function(d) {return d;});
exitは余ったDOMをセレクションとして返すので、removeで不要な要素を削除します。
<div id="fruits"> <p>リンゴ</p> <p>オレンジ</p> <p>バナナ</p> <p>イチゴ</p> </div>
var fruits = ["Apple", "Orange", "Banana"];
d3.select("#fruits").selectAll("p")
.data(fruits).text(function(d) {return d;})
.exit().remove();
SVGの描画
D3.jsでSVGを描画するには、SVG要素をappendで追加します。以下の例ではSVG要素に対してcircle要素を追加し、円を描画しています。SVGの基本図形には円の他に、四角(rect)、楕円(ellipse)、線(line)、折れ線(polyline)、多角形(polygon)などがあります。
var svg = d3.select("body")
.append("svg").attr("width",700).attr("height",400);
var circle = svg.append("circle")
.attr("cx",300)
.attr("cy",200)
.attr("r",180)
.attr("fill","#28cca3") // 塗りつぶしの色
.attr("stroke","#2efac7") // 枠の色
.attr("stroke-width",10); // 枠の太さ
アニメーションの設定
D3.jsでは、データの変化や推移に合わせてさまざまなアニメーションを設定することができます。必要な属性だけを操作することでオーバーヘッドを減らし、高いフレームレートを実現します。以下の例では、300ミリ秒かけてアニメーションしながら、X軸の座標が100pxの位置に円を移動させています。今回はeaseにinを設定しましたが、他にもいくつかアニメーションの種類がありますので、変更して動きを確かめてみてください。
circle
.transition()
.duration(300) // アニメーションにかける時間
.attr("cx", function() { return 100; })
.ease("in") // アニメーションの種類
ここまでのおさらい
ここまでの内容をもとに、円がランダムな位置にアニメーションを伴って生成されるサンプルを作成してみました。
var w = 1024;
var h = 768;
// 円の半径
var radiuses = [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53];
// 円に設定する色
var colors = ["#bdc3c7", "#f39c12", "#2ecc71", "#e74c3c",
"#2c3e50", "#3498db", "#8e44ad", "#e67e22",
"#1abc9c", "#f1c40f", "#2980b9", "#c0392b"];
var svg = d3.select("body").append("svg")
.attr("width", w).attr("height", h);
svg.selectAll("circle)"
.data(radiuses)
.enter()
.append("circle")
// ランダムな位置に生成
.attr("cx", function(d) { return Math.random() * w; })
.attr("cy", function(d) { return Math.random() * h; })
.attr("fill", function(d, i) { return colors[i]; })
// 徐々に大きくなるように半径0を初期値として設定
.attr("r", 0)
.transition()
// それぞれの円を時間差で生成させるための遅延の設定
.delay(function(d, i) { return i * 200; })
.duration(700)
.ease("bounce")
// 最終的に表示される円の半径
.attr("r", function(d) { return d; });
円の半径のリストをデータとしてバインドし、円を生成しています。生成される位置はランダムで、半径0からデータとして与えられた半径までアニメーションしながら大きくなります。easeにはbounceを設定しているので、バウンドしているような動きをします。円はそれぞれ少しずつタイミングがずれて生成されるように、delayで遅延を設定しています。
いかがでしょうか? 少し長くなりましたが、一つ一つの処理は短いので順を追って見ていけば理解できるかと思います。
