私は、種間の関係をマッピングするインタラクティブなエコシステム エクスプローラー ツールを作成するために、しばらくの間 d3 を使用してきました。最近、ユーザーが強制有向グラフで種 (ノード) を表示または非表示にできる機能を追加しようとしました。私は他の例に従ってみましたが、コードは機能しますが、一貫性がありません。
何らかの理由で、ノードを追加し直すと、表示されないことがあります。ノードが追加されたかのようにグラフが移動しますが、表示されません。追加しているように感じますが、ノードは force.on("tick") コードで再び隠されていますが、その理由はわかりません。関連するコードを以下に投稿しました。アイデアをいただければ幸いです。toggleNode 関数は、ノードを表示するか非表示にするかを決定します。基本的には、ノード配列に接合または追加するだけです。ノードが表示されているかどうかを示すフラグを格納するデータセットという配列にデータを保持します。
var force = d3.layout.force()
.gravity(.05)
.distance(100)
.charge(-100)
.size([w, h]);
var nodes = force.nodes(), links = force.links(); // arrays to hold data
var vis = d3.select("#chart").append("svg:svg")
.attr("width", w)
.attr("height", h);
force.on("tick", function() {
vis.selectAll("circle.node")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
vis.selectAll("line.link")
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
});
function restart() {
// UPDATE nodes
var node = vis.selectAll("circle.node")
.data(nodes, function(d) { return d.id;});
// ENTER new nodes
var nodeEnter = node.enter().append("svg:circle")
.attr("class", "node")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.style("fill", function(d) { return groupColors[(d.group)-1]; })
.style("stroke","fff")
.style("stroke-width",1)
.on("mousedown", function(d) {
clickNode(d);
})
.call(force.drag);
// REMOVE deleted nodes
var nodeExit = node.exit().remove();
force.start();
}
// Add the nodes and links to the vis
function createVis(json) {
dataset = json; // store data in global
for (var i = 0; i < dataset['nodes'].length; i++) {
// fill node info
nodes.push(dataset['nodes'][i]);
}
restart();
}
// Remove node and associated links.
function toggleNode(nodeKey,eol_id) {
console.log(nodeKey + ': ' + eol_id);
var tLabel; // value for toggle label
if ( dataset['nodes'][nodeKey]['isHidden'] == 0 ) {
// node is visible, so hide it
tLabel = 'Show';
for( var k=0; k<nodes.length; k++ ) {
if ( nodes[k]['eol_id'] == eol_id ) {
nodes.splice(k, 1); // remove this node
break;
}
}
dataset['nodes'][nodeKey]['isHidden'] = 1;
console.log('node removed: ' + nodeKey);
} else {
dataset['nodes'][nodeKey]['isHidden'] = 0;
nodes.push(dataset['nodes'][nodeKey]);
tLabel = 'Hide';
}
$('#primary_title_toggle').html(' <a href="#" onclick="toggleNode(' + nodeKey + ',\'' + eol_id + '\')">' + tLabel + '</a><br>');
restart();
}