d3.js の Tutorials「Three Little Circles」 を参考にして、円の描画を行います。
以下では、要素の追加、更新、削除を順を追って行います。
目次
1.要素の追加
まずは、svg要素のみ定義されたhtmlに、次の3つの円を追加します。
1−1.ソースコード
円を追加するには次のようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<body> <svg width="700px"></svg> <script> d3.select("svg").selectAll("circle") // ① svg要素を選択し、その子要素のcircle要素を全て選択 .data([10, 20, 30]) // ② 追加するデータ(今回は円の半径として使用) .enter() // ③ 新規追加する circle要素を DOMに反映 .append("circle") // ④ 円を追加 .attr("cy", 60) // ⑤ y軸の座標 .attr("cx", function(d, i) { return i * 100 + 100; }) // ⑥ x軸の座標 .attr("r", function(d) { return d; }) // ⑦ 半径 .style("fill", "steelblue") // 塗りつぶす色 </script> </body> |
1−2.詳細
JavaScriptの各処理について見ていきます。
①
ここでは、svg要素を選択して子要素の全てのcircle要素を選択しています。
ただしhtmlには、svg要素のみ定義しているため現時点ではcircle要素はありません。
circle要素はこれから追加されます。
②
追加するデータを配列で定義しています。今回は半径として使用します。
③
新規追加した要素をDOMに反映します。
この記述をしないと、追加されるcircle要素はDOMに反映されません。
④
円を要素を追加します。(dataで指定された配列分追加)
⑤
属性(cy)はy座標を指定します。
⑥
属性(cx)はx座標を指定します。
今回は、x座標の値を匿名関数で指定しています。
1 |
function(d, i) { return i * 100 + 100; } |
引数 d と i ですが
d:dataでバインドした値が格納されています。
i:インデックス値が格納されています。
今回の匿名関数の処理では、インデックスによりx座標を 100 ずつずらしています。
⑦
属性(r)で円の半径を指定します。
今回使用した匿名関数は、dataでバインドした各データを返します。
1 |
function(d) { return d; } |
2.要素の更新
次に、4つの円を描画して、1で描画した円を更新します。
描画すると次のようになります。
2−1.ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<body> <svg width="700" height="300"></svg> <script> // 初期circle var circle = d3.select("svg").selectAll("circle") .data([10, 20, 30]) .enter() .append("circle") .attr("cy", 60) .attr("cx", function(d, i) { return i * 150 + 100; }) .attr("r", function(d) { return d; }) .style("fill", "steelblue"); // 更新 circle.data([30,40,50,60]) // ① 更新用のデータ .enter() .append("circle") .style("fill", "green") // ② 追加される要素にのみ適用 .merge(circle) // ③ 追加・更新される要素に適用 .attr("cy", 150) .attr("cx", function(d, i) { return i * 150 + 100; }) .attr("r", function(d) { return d; }) .style("stroke", "black"); </script> </body> |
2−2.詳細
JavaScriptの各処理について見ていきます。
大まかな部分は、1と同様なのでポイントのみ見ていきます。
①
更新用のデータを指定します。
②
新たに追加される要素にのみ適用したい設定を行います。
3つの円がある状態から、4つの円を描画しているため、最初に描画した3つの円のcircle要素が再利用(更新)されます。
そのため、不足分の1つの円のみ追加されます。
Demoを見ると追加された4つ目の円にのみ変更が適用されています。
③
merge関数を使って、追加・更新要素の両方に属性やstyleを設定しています。
merge関数を使用しない場合、更新された要素への変更は、DOMに反映されません。
3.要素の削除
次に、2つの円を描画して1で描画した円を更新します。
描画すると次のようになります。
3−1.ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<body> <svg width="700" height="300"></svg> <script> // 初期circle var circle = d3.select("svg").selectAll("circle") .data([10, 20, 30]) .enter() .append("circle") .attr("cy", 60) .attr("cx", function(d, i) { return i * 150 + 100; }) .attr("r", function(d) { return d; }) .style("fill", "steelblue"); // 更新 circle = d3.select("svg").selectAll("circle") .data([30,40]); // ① 更新用のデータ circle.exit().remove(); // ② 余分なデータを削除 circle.enter() .append("circle") .style("fill", "green") // 追加される要素にのみ適用 circle.merge(circle) // 追加・更新される要素に適用 .attr("cy", 60) .attr("cx", function(d, i) { return i * 150 + 100; }) .attr("r", function(d) { return d; }) .style("stroke", "black"); </script> </body> |
3−2.詳細
JavaScriptの各処理について見ていきます。
大まかな部分は、1、2と同様なのでポイントのみ見ていきます。
①
更新用のデータを指定します。
②
circle要素が3つ→2つに減ったため、1つcircle要素が余ってしまいます。
data関数では、余った要素の削除は行わないため、不要な要素がある場合は明示的に削除する必要があります。
もし、削除しない場合は、DOMに残り続けます。
4.まとめ
data関数を使用して、円を描画しました。
描画については、3の例の通り
① データの結合(data)
② 不要な要素の削除(remove)
③ データの追加(enter)
④ 再利用・追加データの更新(merge)
を行うと、もれなく要素をDOMに反映することができます。