2

私はd3.jsを使用して、力のレイアウトを使用してノードとリンクグラフをレイアウトしています。ノードは円で表されます。行によるリンク。特定の状況下で、グラフ上の状態の変化を示すために、線またはノードの視覚的特性(色​​、サイズ、不透明度など)を変更したいと思います。グラフを再描画することでそれを行うことができましたが、それはすべてのノードを揺さぶり、明確ではなく混乱を招きます。

グラフを作成するためのコード:

force = d3.layout.force()
        .charge(-120)
        .gravity(0.2)
        .linkDistance(30)
        .size([width-pad, height-pad]);


nodeSet = svg.selectAll(".qNode");
// BIND NODE DATA
nodeSet = nodeSet.data(chartData.nodes);
// CREATE NODES
nodeSet.enter().append("circle")
    .attr("class", "qNode")
    .attr("r", function(d) { return d.size();})
    .style('stroke-opacity', function(d) { return d.opacity(); })
    .style('stroke', function(d) { return d.color(); })
    .style("fill", function(d) { return color(1); });
//similarly for links.

force.nodes(chartData.nodes).links(chartData.links).start();

グラフを更新するには、次のフラグメントを使用します。

    // SELECT NODES
    nodeSet = svg.selectAll('.qNode');
    // JOIN NODES
    nodeSet = nodeSet.data(force.nodes());
    // UPDATE NODES
    nodeSet.attr("class", "qNode")
    .attr("r", function(d) { return d.size();})
    .style("fill", function(d) { return color(1); })
    .style('stroke', function(d) { return d.color(); })
    .style('stroke-opacity', function(d) { return d.opacity(); })
    .style('opacity', 1)
    .call(force.drag);
    // CREATE NODES
    nodeSet.enter().append("circle")
    .attr("class", "qNode")
    .attr("r", function(d) { return d.size();})
    .style("fill", function(d) { return color(1); })
    .call(force.drag);
    // DELETE NODES
    nodeSet.exit().remove();


    // START SHOW
    force.start();

これを実行すると、新しいストローク属性が適用される前に、グラフ全体が少し揺れます。

d.size()したがって、2つの質問があります。データオブジェクトの状態変化が、、d.color()などに異なる値を返すと仮定します。

  1. ノードを揺さぶることなくグラフの外観を変更するにはどうすればよいですか?
  2. ノードをジグルしたい場合、ジグルするノードのセットを決定できますか?(これにより、どのリンカーノードの外観が変更されたかをユーザーに通知できます。)

編集済み

とりあえずノードの揺れをあきらめましたが、次のコード(@defenestratedによる提案に基づく)は、グラフ内のいくつかのノードとエッジのプロパティを更新するためのトリックを実行しているようです。

var allLinks = ... // my links from a d3 selectAll
var allNodes = ... // my nodes from a d3 selectAll
force = ... // my d3 force layout
function updateGraph(graph, nodeSubset, linkSubset) {
    for (var i=0; i<allLlinks.length; i++)
        allLinks[i].selected = false;
    for (var i=0; i<allNodes.length; i++)
        allNodes[i].selected = false;
    for (var i=0; i<linkSubset.length; i++)
        linkSubset[i].selected = true;
    for (var i=0; i<nodeSubset.length; i++)
         nodeSubset[i].selected = true;

    // these functions modify the selected nodes and links
    linkSubset.call(setLinkAttributes);
    nodeSubset.call(setNodeAttributes);

    if (force.alpha() == 0) {
        force.start();
        force.stop();
    }
}

function setLinkAttributes(links) {
    link.style(...);
}

function setNodeAttributes(nodes) {
    nodes.style(...);
}

start/を呼び出す必要はありません。stopまたは、属性を適用した後resumeもグラフがまだ動いている場合(if alpha() > 0)は、後続のティックが新しい属性を取得するためです。グラフが落ち着いたら、startを呼び出すと、ノードを移動せずにグラフが更新されます。

4

1 に答える 1

1
  1. force.stop()「ノードの更新」ブロックの前と後に呼び出してみforce.resume()ましたか?

  2. 状態に基づいて分類することができます。したがって、.attr("id", "changed")更新中のノードにを適用し、それをd3選択で使用します。changedNodes =d3.select("#changed")

于 2013-02-16T22:11:25.240 に答える