こちらのサイト(Thinking with Joins)を参考に、D3.jsの enter、update、exit の使い方をまとめました。
目次
1.enter、update、exit の各役割を簡単にまとめると
enter
新しく生成した要素を扱います。
例えば、新しくdiv要素を生成した場合、div要素へ更新内容を反映します。
なので、新しく生成した要素に enter を使用しない場合、更新が反映されないのでブラウザに更新内容が表示されません。
update
既存の要素を扱います。
例えば、既存のdiv要素になんらかの変更を行った場合、div要素へ更新内容を反映します。
exit
既存の余分な要素を扱います。
例えば、div1、div2、div3 という要素があり、 div1、div2のみ更新しdiv3は必要ない場合は、何もしないとdiv3も残り続けるので、exit().remove(); とすると不要なdiv3の要素を削除することができます。
以降では、各役割を個別に検証します。
2.enter:新しく生成した要素を更新
2-1.新しくdiv要素を追加
html
1 |
<div id="chart"></div> |
javascript
1 2 3 4 5 6 7 8 |
var data = [”1”, ”2”, ”3”]; d3.select("#chart") .selectAll("div") .data(data) .enter() .append("div") .style("color", "red") .text(function(d) { return “div:” + d; }); |
この例では、変数data配列の要素分 <div id=”chart”></div> の内部に、div要素を3つ追加します。
ただし、<div id=”chart”></div> の内部にdiv要素は1つも無いため、新たに div要素を3つ生成して追加します。
ここで、enter を使用することで、新しく追加した要素がブラウザに反映されます。
Demoの実行結果は以下のようになります。
<ブラウザの表示>
<html>
1 2 3 4 5 |
<div id="chart"> <div style="color: red;">create div element1</div> <div style="color: red;">create div element2</div> <div style="color: red;">create div element3</div> </div> |
2-2.もし、enter を使わなかったらどうなるか?
javascript を変更し、enter を使わないようにします。
1 2 3 4 5 6 7 8 |
var data = [”1”, ”2”, ”3”]; d3.select("#chart") .selectAll("div") .data(data) // .enter() .append("div") .style("color", "red") .text(function(d) { return “div:” + d; }); |
この場合、実行後のhtmlは以下のようになり
1 |
<div id="chart"></div> |
enter を使わなかったことで、新たに生成したdiv要素が反映されません。
2-3.既に div要素が存在する場合は?
続いて、既に div要素がいくつか存在する場合に、enter を使用するとどうなるか確認します。
以下の例では、既存で div要素が1つある html に 3つ div要素を追加します。
※3つ div要素を追加しますが、d3.jsでは既存の要素も流用します。
なので、この場合は 既存の div要素を流用し不足分のdiv要素(2つ)を新たに追加します。
html
1 2 3 |
<div id="chart"> <div></div> </div> |
javascript
1 2 3 4 5 6 7 8 9 10 |
<script> var data = ["1", "2", "3"]; d3.select("#chart") .selectAll("div") .data(data) .enter() .append("div") .style("color", "red") .text(function(d) { return "create div element:" + d; }); </script> |
<実行結果>
ブラウザ
html
1 2 3 4 5 |
<div id="chart"> <div></div> <div style="color: red;">create div element:2</div> <div style="color: red;">create div element:3</div> </div> |
実行結果を見ると、既存のdiv要素に対する変更は反映されていませんが、新たに追加された div要素 には反映されています。
なぜ、既存のdiv要素には変更が反映されていないかというと、enter は
新しく生成した要素を扱う
からです。
なので、既存のdiv要素への変更は、enter では 反映することができません。
既存要素への反映は、update で扱います。
3.update:既存の要素を更新
3-1.既存の要素に変更を反映させるには?
enter をつけないと update処理になります。
html
1 2 3 |
<div id="chart"> <div></div> </div> |
javascript
1 2 3 4 5 6 7 |
var data = ["1", "2", "3"]; d3.select("#chart") .selectAll("div") .data(data) .append("div") .style("color", "red") .text(function(d) { return "create div element:" + d; }); |
<実行結果>
ブラウザ
html
1 2 3 4 5 |
<div id="chart"> <div> <div style="color: red;">create div element:1</div> </div> </div> |
実行結果から、既存のdiv要素のみ変更が反映されていることが分かります。
新たに生成された 2つの div要素については enter を使わなかったため、変更が反映されませんでした。
3-2.新規・既存要素どちらにも変更を反映させるには?
新規・既存要素のどちらにも変更を反映させるには、merge() を使います。
html
1 2 3 |
<div id="chart"> <div></div> </div> |
javascript
1 2 3 4 5 6 7 |
var data = ["1", "2", "3"]; var div_data = d3.select("#chart").selectAll("div").data(data); div_data.enter().append("div") .<span class="red">merge(div_data)</span> .style("color", "red") .text(function(d) { return "create div element:" + d; }); |
<実行結果>
ブラウザ
html
1 2 3 4 5 |
<div id="chart"> <div style="color: red;">create div element:1</div> <div style="color: red;">create div element:2</div> <div style="color: red;">create div element:3</div> </div> |
実行結果から、新規・既存要素のどちらにも変更が反映されていることが分かります。
4.exit:既存の余分な要素を扱う
余分な要素とは?
例えば、既存でdiv要素が3つある場合に、設定するデータが2つしか無い場合、1つ余分になってしまいます。
余分になった要素をそのままにしておくと、ブラウザに表示されます。
ブラウザに表示されても大丈夫な場合は、放置していても大丈夫ですが、削除したい場合は、exitを使用して余分な要素を削除します。
html
1 2 3 4 5 |
<div id="chart"> <div></div> <div></div> <div></div> </div> |
javascript
1 2 3 4 5 6 7 8 |
var data = ["1", "2"]; var div_data = d3.select("#chart") .selectAll("div") .data(data) .style("color", "red") .text(function(d) { return "create div element" + d; }) div_data.exit().remove(); |
<実行結果>
ブラウザ
html
1 2 3 4 |
<div id="chart"> <div style="color: red;">create div element1</div> <div style="color: red;">create div element2</div> </div> |
実行結果から、divの要素が1つ消えていることが分かります。
5.結局どうすればいいのか?
enter、update、exit をどのような流れで使えば良いのか?
こちらのサイト(Thinking with Joins)には以下のように記載されています。
① 使用するデータをセット
② 余分な要素を削除
③ 新規・更新要素の変更を反映
コードにすると・・・
html
1 2 3 4 5 |
<div id="chart"> <div></div> <div></div> <div></div> </div> |
javascript
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<script> var data = ["1", "2"]; // ① データをセット var div_data = d3.select("#chart").selectAll("div").data(data); // ② 余分な要素を削除 div_data.exit().remove(); // ③ 新規・更新要素の変更を反映 div_data.enter().append("div") .merge(div_data) .style("color", "red") .text(function(d) { return "create div element:" + d; }); </script> |
若干コードが長くなりますが、余分な要素を削除でき、要素も再利用できます!
あとはお好みで使う/使わないの判断でしょうか。