【发布时间】:2018-07-05 21:17:08
【问题描述】:
我有一个力导向图,其中包含(大量)节点以及它们之间的许多链接。我想以交互方式应用过滤器,以便只保留一部分节点(以及它们之间的任何链接)。但是,由于图表很大,我想从模拟中删除任何被过滤掉的节点,而不是仅仅隐藏它们(以便生成的图表具有更好的性能)。因此,我希望创建一个过滤的节点列表作为新数组,并仅使用这些节点重新初始化模拟。同样适用于边缘 - 我还没有这样做,但我可能需要以编程方式确定要保留哪些边缘并在使用新节点 和 边缘重新初始化图形之前进行相同类型的过滤.我想保留原始节点/边数组以允许“重置”回到起始状态。
我已经整理了一个简单的示例,此时它只是进行一些硬编码过滤,但我正在努力使用过滤后的数组重新初始化模拟。它似乎正在从模拟中删除过滤后的节点(圆圈“三”不再可拖动),但它仍然显示在渲染图中。
到目前为止,我对“重置”逻辑的尝试似乎确实有效。
我做错了什么?有没有更好的方法来实现这一目标? (d3.js v3)
我的示例代码如下:
var links = [{
source: 0,
target: 1,
type: "c"
},
{
source: 1,
target: 2,
type: "d"
},
{
source: 2,
target: 0,
type: "d"
}
];
var nodes = [{
name: "one",
type: "a"
},
{
name: "two",
type: "a"
},
{
name: "three",
type: "b"
}
];
var width = 300;
var height = 300;
var force = d3.layout.force()
.nodes(nodes)
.links(links)
.size([width, height])
.linkDistance(200)
.charge(-400)
.on("tick", tick)
.start();
var svg = d3.select("#graph").append("svg")
.attr("width", width)
.attr("height", height);
function colours(n) {
var colours = ["#3366cc", "#dc3912", "#ff9900", "#109618", "#990099", "#0099c6", "#dd4477", "#66aa00", "#b82e2e", "#316395",
"#994499", "#22aa99", "#aaaa11", "#6633cc", "#e67300", "#8b0707", "#651067", "#329262", "#5574a6", "#3b3eac"
];
return colours[n % colours.length];
}
var path = svg.append("g").selectAll("path")
.data(force.links())
.enter().append("line")
.attr('class', 'link')
.attr('stroke', function(d, i) {
return colours(i);
})
var circles = svg.append("g");
var circle = circles.selectAll("circle")
.data(force.nodes())
.enter().append("circle")
.attr("r", 8)
.attr('class', 'circle')
.attr('fill', function(d, i) {
return colours(i + 3);
})
.call(force.drag);
var text = svg.append("g").selectAll("text")
.data(force.nodes())
.enter().append("text")
.attr("x", 14)
.attr("y", ".31em")
.text(function(d) {
return d.name;
});
function tick() {
path.attr({
x1: function(d) {
return d.source.x;
},
y1: function(d) {
return d.source.y;
},
x2: function(d) {
return d.target.x;
},
y2: function(d) {
return d.target.y;
}
});
circle.attr("transform", transform);
text.attr("transform", transform);
}
function transform(d) {
return "translate(" + d.x + "," + d.y + ")";
}
var nodeText = "";
function nodeTypeA(node) {
return (node.type == "a");
}
function linkTypeC(link) {
return (link.type == "c");
}
function applyFilter() {
force.nodes(nodes.filter(nodeTypeA));
force.links(links.filter(linkTypeC));
circle.data(force.nodes());
text.data(force.nodes());
path.data(force.links());
d3.selectAll("circle").each(
function(d) {
console.log(d.name);
}
);
console.log("");
}
function resetFilter() {
force.nodes(nodes);
force.links(links);
circle.data(force.nodes());
text.data(force.nodes());
path.data(force.links());
d3.selectAll("circle").each(
function(d) {
console.log(d.name);
}
)
console.log("");
}
#buttons {
position: absolute;
top: 10px;
left: 20px;
height: 100px;
width: 400px;
z-index: 99;
}
#graph {
position: absolute;
top: 50px;
left: 20px;
height: 300px;
width: 300px;
z-index: 98;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<div id="root">
<div id="buttons">
<button id="filter" onclick="applyFilter()">Apply</button>
<button id="reset" onclick="resetFilter()">Reset</button>
</div>
<div id="graph">
</div>
</div>
</body>
<div id="node_details">
</div>
</body>
【问题讨论】:
-
你能把这个例子放在一个 sn-p (或 plunkr, jsfiddle...) 中,以便于执行和编辑吗?参考文献stackoverflow.blog/2014/09/16/…
-
当然。将示例移至 sn-p。
标签: javascript d3.js