huruyosi’s blog

プログラミングとかインフラとかのメモです。

d3.js の General Update Pattern, I を読む

huruyosi.hatenablog.com

の続きです。

漠然と、d3.jsで作成したグラフを動的に更新する方法が分からないのでd3.js でデータを更新する方法を理解するために General Update Pattern, I を読んでみます。

やっていること。

f:id:huruyosi:20160131104502p:plain

a~zの文字列を任意に抽出して表示しています。表示する時に追加された部分を緑の文字にしています。ここでの「追加」はd3.jsでは.enter()の対象になるデータを指しています。

たとえば、「fjopqy」の次に「acdghijlnopqtr」が生成されたら要素6のj以降が追加されたデータになります。

要素n 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
前回 f j o p q
今回 a c d f g h i l q r t u w x y

減った要素は .exit()の対象になり.remove()で削除されます。

具体的な処理

// 表示するアルファベットの配列を作成します。
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.
  // データを与え、textタグを作ります。
  var text = svg.selectAll("text")
      .data(data);

  // UPDATE
  // Update old elements as needed.
  // 更新されたデータが対象
  // 前回の処理でも存在した要素のclassにupdateを指定することで文字色を指定します。
  text.attr("class", "update");

  // ENTER
  // Create new elements as needed.
  // 追加されたデータが対象
  // 前回の処理よりも増えた要素は新たななtextタグを作成し文字色を指定します。
  // また"x"属性で文字の横位置を指定し、"dy"でサイズを指定します。
  text.enter().append("text")
      .attr("class", "enter")
      .attr("x", function(d, i) { return i * 32; })
      .attr("dy", ".35em");

  // 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.
  // 追加と更新されたデータが対象
 // 描画する文字を指定します。
  text.text(function(d) { return d; });

  // 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);

 やっと分かったこと

セクションの仕組みの 悟りの鍵 を読んだことで、データと描画の関係が分かってきた気がする。.date(data)で与えられたデータを d3.jsが保持しているデータと比較し増減があれば、.enter()で増加分の処理を行い、.exit()でなくなった分の処理を行っていけばいい。

書き換えは少し不安があるけど、文字の書き換えは.text()で描画したい文字を与えればいい。