d3.js の General Update Pattern, II を読む
データにキーを持たせる方法
d3.js の General Update Pattern, I を読む - huruyosi’s blog でのデータ更新は配列の要素に基づいた方法であったので、サンプルを見ていても「更新」されたとするデータがみためとはずれている感覚がありました。
General Update Pattern, II ではデータにキーを持たせることで見た目とのズレがなくなりました。
二つのソースを比べるとデータの与え方を変え、それによって.enter()
で行う要素の追加と文字の描画方法も変えています。
データの与え方
var text = svg.selectAll("text") .data(data, function(d) { return d; });
dataメソッドの第2引数にデータに対応する一意なキーを返す無名関数を指定しています。第2引数の無名関数の引数にはデータが与えられるので、このサンプルではアルファベット1文字が渡ってきます。引数をそのまま返すことで、アルファベットがキーになり、値も同じアルファベットになります。
https://github.com/mbostock/d3/wiki/Selections#data
2回目以降の dataメソッドの呼び出しでは、同一のキーであればデータが更新され、新たなキーであれば追加なので.enter()
の対象になり、無くなったキーであれば削除なので.exit()
の対象になります。
データが追加された
text.enter().append("text") .attr("class", "enter") .attr("dy", ".35em") .text(function(d) { return d; });
前回と違うのは .attr("x", function(d, i) { return i * 32; })
がなくなり、.text(function(d) { return d; })
が追加されています。キーと値が同じなので、.text
でレンダリングする文字は変化しないので追加時に設定します。一方、文字を描画するx座標は毎回変化することが考えられるので、はずされています。
追加と更新されたデータのX座標
text.attr("x", function(d, i) { return i * 32; })
データのn番目に基づいて文字を描画するx座標を決めています。
無くなったデータ
text.exit().remove();
d3.js の General Update Pattern, I を読む - huruyosi’s blog と同様に削除しています。
処理
// 表示するアルファベットの配列を作成します。 var alphabet = "abcdefghijklmnopqrstuvwxyz".split(""); var width = 960, height = 500; // svgタグを作成し、gタグを縦方向の中央に移動します。 var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height) .append("g") .attr("transform", "translate(32," + (height / 2) + ")"); function update(data) { // DATA JOIN // Join new data with old elements, if any. // データとデータのキーを取得する無名関数を与えます。 var text = svg.selectAll("text") .data(data, function(d) { return d; }); // UPDATE // Update old elements as needed. // 更新されたデータ // 前回の処理でも存在した要素のclassにupdateを指定することで文字色を指定します。 text.attr("class", "update"); // ENTER // Create new elements as needed. // 追加されたデータが対象 // 前回の処理よりも増えた要素は新たななtextタグを作成し文字色を指定します。 // また"text"属性で描画する文字を、"dy"属性でサイズを指定します。 text.enter().append("text") .attr("class", "enter") .attr("dy", ".35em") .text(function(d) { return d; }); // ENTER + UPDATE // Appending to the enter selection expands the update selection to include // entering elements; so, operations on the update selection after appending to // the enter selection will apply to both entering and updating nodes. // 追加と更新されたデータが対象 // データのn番目に基づいて描画する文字のx座標を"x"属性で指定します。 text.attr("x", function(d, i) { return i * 32; }) // EXIT // Remove old elements as needed. // 削除されたデータが対象 // 前回の処理では存在し、今回の処理では存在しない要素を削除します。 text.exit().remove(); } // The initial display. // 最初の表示を行います。a~zまでの文字が描画されます。 update(alphabet); // Grab a random sample of letters from the alphabet, in alphabetical order. // 1.5秒ごとにアルファベットをランダムに決め、アルファベット順に表示します。 setInterval(function() { update(d3.shuffle(alphabet) .slice(0, Math.floor(Math.random() * 26)) .sort()); }, 1500);