enter、update、exitの関係

      enter、update、exitの関係 はコメントを受け付けていません

d3を学ぶ上で一番難しいのはenter、update、exitの関係でしょう。この中で、updateは特に明示するわけではないのも混乱の元です。
このページでは、復習も兼ねてそれぞれの役割を確認してみます。
まずは、datasetの要素数に合わせてdivとテキストを作成するサンプルから始めます。

enter_update_exit_start

enterとupdate

すでに、追加と削除ボタンが付いているのでこれを利用して、まずは新しくdatasetの要素数を増やしてみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//クリックするとdatasetを更新して要素数を7にする////////////////////
d3.select(".add")
   .on("click", function() {
 
      //datasetの新しい値
      dataset = [ 5, 10, 15, 20, 25, 30, 35 ];
 
      var divs = body.selectAll("div") //divのDOM要素が7になるように選択し直す。
         .data(dataset);          //データの要素数をカウントし抽出。updateセレクションに入る
 
      //enterセレクション。DOM要素がデータの要素数より少ない場合は新しく空のDOM要素を作る。
      divs.enter()
         .append("div")            //新しく作ったDOM要素にdivを追加。
         .text(function(d){      //divの中にテキストを追加。
            return "新しい数値は" + d + "になります";
         })
         .style("color", "blue"); //全てのp要素に適用
   });

このコードのポイントは、.data(dataset)以降です。

まず、データの要素数をカウントし抽出します。

1
.data(dataset)

次に、.enter()で、DOM要素がデータの要素数より少ない場合は新しく空のDOM要素を作ります。

1
.enter()

新しく作ったDOM要素にdivを追加します。

1
.append("div")

新しく作ったdivにテキストを追加します。

1
2
3
.text(function(d){      //<p></p>の中にテキストを追加。
   return "新しい数値は" + d + "になります";
})

最後に、新しく作ったdivの色(テキストの色)を赤にします。

1
.style("color", "blue"); //全てのp要素に適用

「追加」をクリックしてみると、新しく追加された要素だけが青になります。これは、enter()によって行われる更新は、新しいdiv要素にのみ適用されるからです。


全て更新したい場合はどうすればいいでしょうか。答えは簡単で、もう一度全てのdivを選択し直して、更新します。ここではupdateというコードは出てきませんが、実際にはupdate()を実行しています。

1
2
3
4
5
6
7
8
9
10
11
12
13
var divs = body.selectAll("div") //divのDOM要素が7になるように選択し直す。
   .data(dataset)          //データの要素数をカウントし抽出。updateセレクションに入る
 
//enterセレクション。DOM要素がデータの要素数より少ない場合は新しく空のDOM要素を作る。
divs.enter()
   .append("div")            //新しく作ったDOM要素にdivを追加。
   .text(function(d){      //divの中にテキストを追加。
      return "新しい数値は" + d + "になります";
   })
   .style("color", "blue"); //全てのp要素に適用
 
//update
divs.style("color", "blue");

全て青に変更できました。

merge(結合)

実は、新しく増えたdivと既存のdivの更新はもっと短いコードで同時に行うことができます。merge()(結合という意味の英語)を使います。

1
2
3
4
5
6
7
8
9
10
11
var divs = body.selectAll("div") //divのDOM要素が7になるように選択し直す。
   .data(dataset)          //データの要素数をカウントし抽出。updateセレクションに入る
 
//enterセレクション。DOM要素がデータの要素数より少ない場合は新しく空のDOM要素を作る。
divs.enter()
   .append("div")            //新しく作ったDOM要素にdivを追加。
   .text(function(d){      //divの中にテキストを追加。
      return "新しい数値は" + d + "になります";
   })
   .merge(divs)       //既存のdiv要素も一緒に選択する
   .style("color", "blue"); //全てのp要素に適用

同じ結果になります。

exit

次に、datasetの要素が減った時の動作をexit()で操作してみましょう。以下のコードを追加します。

1
2
3
4
5
6
7
8
9
10
11
12
//クリックするとdatasetを更新して要素数を4にする////////////////////
d3.select(".remove")
   .on("click", function() {
 
      //datasetの新しい値
      dataset = [ 5, 10, 15, 20 ];
 
      body.selectAll("div")
         .data(dataset)          //データの要素数をカウントし抽出
         .exit()
         .style("color", "red"); //exit()のp要素に適用
   });

ここでは、datasetの要素が4個に減っているので、「追加」によって増えた7個から3個減っています。exitによって、データがなくなってしまったdiv要素を選択し、style()で赤に変更しています。

一般的には余分なdiv要素は削除するので、remove()しましょう。

1
2
3
4
5
body.selectAll("div")
   .data(dataset)          //データの要素数をカウントし抽出
   .exit()
   //.style("color", "red"); //exit()のp要素に適用
   .remove();

enter_update_exit

まとめ

よって、enter, update, exitの関係は以下になります。

enter : データセットに追加され、まだDOM要素になっていないもの
update : すでにDOM要素になっている既存のデータ
exit : DOM要素として描画されていて、データセットから削除されたもの

この関係性を忘れないようにしましょう。