请看看我的jsFiddle它具有以下关联数据:
rules = [['L5', 'L2'], ['L5', 'L2'], ['L4', 'L2'], ['L2', 'L1'], ['L3', 'L1'], ['L1', 'C1'], ['C1', 'R2'], ['C1', 'R3'], ['R2', 'R4'], ['R3', 'R6'], ['R3', 'R7']];
,我的目标是有一个可以用来删除图中圆圈的按钮。例如,当我按 e 按钮时,我删除 R3、R2、L5。完成后,我需要在以下之间建立新的连接: 如果删除 R3,则 R7 和 R6 应指向 C1 如果删除 R2,则 R5 应连接到 C1 如果是 L5,则不应创建新连接。
如果您有任何意见、建议或想法 - 那就完美了。当然,我总是可以遍历源代码并删除不需要的圆圈并创建新的连接,但我正在寻找比这更有效的方法+我还将有一个撤消按钮,它可以恢复所做的任何更改,但一次一个问题。
谢谢!
请您参考如下方法:
这称为网络投影,您不应将其视为删除节点,而应将其视为将节点转换为边。这并不是说从 D3 的角度来看您对任务的理解是错误的 — 您需要删除并创建新节点,但使用正确的术语将引导您找到其他示例。当您采用一种类型的网络节点(例如论文)并将它们用作边缘来连接另一种类型的节点(例如人)以将人员网络及其所写的论文转变为连接到的人员网络时,就会发生多模态网络投影与他们一起写论文的人。
要使用 D3 实现这一目标,您必须做一些事情。
首先,您的链接和边缘需要有唯一的 ID,并在绑定(bind)数据时使用它们。当您想要使用 D3 进行复杂的更新和删除元素时,这通常是必要的:
d3.selectAll(".link")
.data(links, function (d) {return d.id})
d3.selectAll(".node")
.data(nodes, function (d) {return d.id})
在您的情况下,这些唯一的 ID 可以是节点的节点名称和链接的连接节点的串联节点名称。
有了这个,您就可以构建一个像这样的简单函数,当您单击节点时会触发该函数:
function collapseNode(d,i) {
force.stop();
removedLinks = links.filter(function (p) {return p.source == d.id || p.target == d.id});
filteredLinks = links.filter(function (p) {return p.source != d.id && p.target != d.id});
filteredNodes = nodes.filter(function (p) {return p.id != d.id});
//create new links
//this will have problems with parallel edges
for (x in removedLinks) {
for (y in removedLinks) {
if (removedLinks[x].source != d && removedLinks[y].source != d) {
filteredLinks.push({source: removedLinks[x].source, target: removedLinks[y].source,
id: generateAnID})
}
else if (removedLinks[x].target != d && removedLinks[y].source != d) {
filteredLinks.push({source: removedLinks[x].target, target: removedLinks[y].source,
id: generateAnID})
}
else if (removedLinks[x].source != d && removedLinks[y].target != d) {
filteredLinks.push({source: removedLinks[x].source, target: removedLinks[y].target,
id: generateAnID})
}
else if (removedLinks[x].target != d && removedLinks[y].target != d) {
filteredLinks.push({source: removedLinks[x].target, target: removedLinks[y].target,
id: generateAnID})
}
}
}
d3.selectAll(".node").data(filteredNodes, function(d) {return d.id})
.exit()
.remove();
d3.selectAll(".link").data(filteredLinks, function(d) {return d.id})
.exit()
.remove();
d3.selectAll(".link").data(filteredLinks, function(d) {return d.id})
.enter()
.append("line)
.attr("class", "line")
force.start();
}