web-dev-qa-db-ja.com

基になるデータが変更されたときにD3強制レイアウトの要素を更新する方法

フォースレイアウトの例( http://bl.ocks.org/1153292 )の1つを使用して、Webサイトにネットワークを表示しています。

ユーザーがいつでも表示するリンクのタイプを選択できるようにします。リンクタイプA、リンクタイプBの追加、リンクタイプAの削除を選択すると、タイプBの残りのリンクはAの色で表示されます。

これは、svgダイアグラムへのリンクを追加するために実行されるコードです。配列を変更していますthis.linksリンクを追加および削除します。ご覧のとおり、クラス属性を設定していますが、更新されていません。リンクAのタイプのままです。

var path = svg.append("svg:g")
    .selectAll("path")
    .data(this.links)
   .enter()
    .append("svg:path")
    .attr("class", function(d) { return "link " + d.type; })
    .attr("marker-end", function(d) { return "url(#" + d.type + ")"; });

現在、tick関数内のクラス属性を更新することでこの問題を回避していますが、これは当然、不要な作業の多くを引き起こします。

Enter操作は、存在する要素と新しい要素のマージされた選択を返すため、attr操作は既存の要素を更新して新しい要素を設定する必要があることを読みました。

何が欠けていますか?

21
Ido Ran

この投稿の回答 が見つかりました

var circle = svg.selectAll("circle")
    .data(data);

circle.enter().append("circle")
    .attr("r", 2.5);

circle
    .attr("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return d.y; });

circle.exit().remove();

その答えは、append演算子の結果ではなく、selectAll.dataの結果に対してattr演算子を呼び出す必要があるということです。

19
Ido Ran

http://bl.ocks.org/1095795 に、強制指定レイアウトからのノードの追加と削除を示す例があります。リンクとノードを個別に処理してから、強制レイアウトを再開する必要があります。

function restart() {
  var link = vis.selectAll("line.link")
      .data(links, function(d) { return d.source.id + "-" + d.target.id; });

  link.enter().insert("svg:line", "g.node")
      .attr("class", "link");

  link.exit().remove();

  var node = vis.selectAll("g.node")
      .data(nodes, function(d) { return d.id;});

  var nodeEnter = node.enter().append("svg:g")
      .attr("class", "node")
      .call(force.drag);

  nodeEnter.append("svg:image")
      .attr("class", "circle")
      .attr("xlink:href", "https://d3nwyuy0nl342s.cloudfront.net/images/icons/public.png")
      .attr("x", "-8px")
      .attr("y", "-8px")
      .attr("width", "16px")
      .attr("height", "16px");

  nodeEnter.append("svg:text")
      .attr("class", "nodetext")
      .attr("dx", 12)
      .attr("dy", ".35em")
      .text(function(d) { return d.id });

  node.exit().remove();

  force.start();
}
4
Bill