我正在尝试从Force Layout中删除一些节点。
该过程的第一部分是选择一个或多个节点。这是通过点击处理程序完成的:
var nodeg = node.enter().append("g")
.attr("class", "node")
.on('click', function (n) {
if (n.dragging === true) {
return;
}
// select the clicked node
n.selected = !n.selected;
d3.select(this)
.transition()
.duration(500)
.ease('bounce')
.attr('fill', getNodeBackground(n))
.attr('transform', getNodeTransform(n));
})
.call(drag);
请注意,我将selected
设置为true。
接下来,如果用户按下delete
键,我将删除所选节点:
function removeSelectedNodes() {
if (!confirm('Are you sure you want to delete the selected relationships?')) {
return;
}
var firstIndex = -1;
d3.selectAll('.node')
.each(function (n, i) {
if (n.selected !== true) {
return;
}
n.data.remove = true;
n.data.index = i;
if (firstIndex === -1) {
firstIndex = i;
}
});
var offset = 0;
_.each(_.where(scope.nodes, {data: {remove: true}}), function (n) {
var removeAt = n.index;
if (n.index > firstIndex) {
removeAt = n.index - 1 - offset;
offset++;
}
scope.nodes.splice(removeAt, 1);
scope.links.splice(removeAt - 1, 1);
});
renderGraph();
}
整个renderGraph
函数如下所示:
function renderGraph() {
force
.nodes(scope.nodes)
.links(scope.links)
.start();
var link = svg.selectAll(".link")
.data(scope.links);
link.exit().remove();
link.enter().append("line")
.attr("class", "link");
var node = svg.selectAll(".node")
.data(scope.nodes);
node.exit().remove();
var nodeg = node.enter().append("g")
.attr("class", "node")
.on('click', function (n) {
if (n.dragging === true) {
return;
}
// select the clicked node
n.selected = !n.selected;
d3.select(this)
.transition()
.duration(500)
.ease('bounce')
.attr('fill', getNodeBackground(n))
.attr('transform', getNodeTransform(n));
})
.call(drag);
nodeg.append("image")
.attr("xlink:href", function (d) {
return d.avatar || 'https://github.com/favicon.ico'
})
.attr("x", -56)
.attr("y", -8)
.attr("width", 64)
.attr("height", 64);
nodeg.append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.attr('class', 'name')
.text(function (d) {
return d.displayName;
});
nodeg.append("text")
.attr("dx", 12)
.attr("dy", "1.35em")
.text(function (d) {
return d.relationship;
});
force.on("tick", function () {
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;
});
node.attr("transform", function (d) {
return getNodeTransform(d);
});
});
}
这是它开始向南的地方。如果我选择一个节点,则在拼接节点后正确呈现图形。但是,如果我删除两个节点,图表最终会保留第一个删除的节点(按索引)。
假设第一个节点(按索引)是'Bob',第二个节点是'Bill'。第二个节点将被删除,但第一个节点将保留。有趣的是,另一个节点,当前的最后一个节点(按索引)将会消失。
注意:数组看起来不错。我想删除的节点已经消失,剩下的节点都是正确的。
我在这里做错了什么?
更新:删除节点后,我尝试未设置 nodes
和links
,只是 start
:
force.start()
这不起作用。
答案 0 :(得分:1)
再次感谢Lars,答案是为链接和节点添加一个关键功能:
var link = svg.selectAll(".link")
.data(scope.links, function (d) {
return d.source.data._id + '|' + d.target.data._id;
});
var node = svg.selectAll(".node")
.data(scope.nodes, function (d) {
return d.data._id;
});
谢谢Lars!