11
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

D3.js v4のデータバインド

Last updated at Posted at 2016-09-20

version4ではかなり挙動が変わっているようだ

過去記事: D3.jsアプリケーション設計におけるデータとDOM操作の分離
http://qiita.com/mojaie/items/1c8ba9d70ab633938a1c

  • 環境
    • D3.js version 4.2.4
    • Google Chrome version 52.0.2743.116

公式サイトの例
https://github.com/d3/d3-selection

var circle = svg.selectAll("circle") // 1
  .data(data) // 2
    .style("fill", "blue"); // 3

circle.exit().remove(); // 4

circle.enter().append("circle") // 5
    .style("fill", "green") // 6
  .merge(circle) // 7
    .style("stroke", "black"); // 8

上記コードを順を追って説明すると、

  1. svgの全てのcircle要素を選択
  2. circleに対応するデータを更新する
  3. データと対応しているcircleを青で塗りつぶす
  4. 対応するデータが無くなったcircleを削除
  5. 新しく加わったデータのcircle要素を作成して選択
  6. 新しく作成したcircleを緑で塗りつぶす
  7. 新しく作成したcircleに加えて既に存在するcircleも選択
  8. 全てのcircleの縁を黒で書く

v4ではmergeが実装されたことで、enterした要素と既存の要素の挙動をまとめて指定できるようになっている。便利。

依然として面倒なのは、一つの親要素が複数の子要素を持っていたり、要素が入れ子になっていたりしているケース。

<ul>
  <li>
    <label>
      <input type="checkbox" name="person" value="1"></input>
      <span>John</span>
    </label>
  </li>
  <li>以下略</li>
</ul>

データを持っているのはliだが、更新するのはその下の階層のinputとspanということになる。selectAll('li').htmlでゴリ押ししてもいいのだが...

function checkboxList(selection, data, name, key, text) {
  const items = selection.selectAll('li').data(data, key);
  items.exit().remove();
  const entered = items.enter().append('li').append('label');
  entered.append('input');
  entered.append('span');
  const updated = entered.merge(items.select('label'));
  updated.select('input')
    .attr('type', 'checkbox')
    .attr('name', name)
    .attr('value', key);
  updated.select('span')
    .text(text);
}

mergeされる2つのselectionの階層が異なる場合、mergeを呼び出す側のselectionに統一される(上記コードの場合、entered.merge(items)でも結果は変わらない、多分)が、開発者の意図した使い方ではないらしいのでmergeするselectionは揃えたほうが無難だろうか。

上記checkBoxListを呼び出す処理は以下の様な感じ。

d3.select('ul')
  .call(checkboxList, [{key: 1, name: 'John'}],
        'person', d => d.key, d => d.name)
  .on('change', () => {
    変更時の処理
  });

callメソッドは実行結果に関係なく必ず呼び出し元のselectionを返すので、UIコンポーネントの生成をルーチン化するのに便利。

11
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?