私は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()
などに異なる値を返すと仮定します。
- ノードを揺さぶることなくグラフの外観を変更するにはどうすればよいですか?
- ノードをジグルしたい場合、ジグルするノードのセットを決定できますか?(これにより、どのリンカーノードの外観が変更されたかをユーザーに通知できます。)
編集済み
とりあえずノードの揺れをあきらめましたが、次のコード(@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を呼び出すと、ノードを移動せずにグラフが更新されます。