我正在尝试关注此D3 Javascript链接:> http://bl.ocks.org/mbostock/1093130了解点击事件的工作原理。不幸的是,我无法完全理解整个代码。我现在要做的是点击蓝色节点时,将显示另外两个节点及其链接。当我再次单击同一节点时,两个节点及其链接必须隐藏。如果我点击其他两个节点中的一个节点,则不会发生任何事情。
这是JSON文件:
{
"nodes": [
{
"name": "Node1",
"group": 2
},
{
"name": "Node2",
"group": 1
},
{
"name": "Node3",
"group": 1
}
],
"links": [
{
"source": 0,
"target": 1,
"value": 2
},
{
"source": 0,
"target": 2,
"value": 2
}
]
}
这是我的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<style>
.node {
stroke: #fff;
stroke-width: 1.5px;
}
.link {
stroke: #999;
stroke-opacity: .6;
}
</style>
<body>
<p>Are you there!!!</p>
<script type="text/javascript" src="d3/d3.v3.js"></script>
<script>
var width = 960,
height = 500;
d3.json("sample.json", function(error, graph) {
var color = d3.scale.category20();
var force = d3.layout.force()
.charge(-120)
.linkDistance(30)
.size([width, height]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
force
.nodes(graph.nodes)
.links(graph.links)
.start();
var link = svg.selectAll(".link")
.data(graph.links)
.enter().append("line")
.attr("class", "link")
.style("stroke-width", function(d) { return Math.sqrt(d.value); });
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", 5)
.style("fill", function(d) { return color(d.group); })
.call(force.drag);
node.append("title")
.text(function(d) { return d.name; });
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("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
});
</script>
</body>
</html>
请有人帮我解决这个问题。非常感谢您的协助。
答案 0 :(得分:10)
您可以按以下步骤单击该节点,分解打开/关闭节点邻居/边缘可见性所需的步骤:
on("click", function(){ ... })
。我创建了一个演示此方法的JSFiddle。要强调的要点是,首先,我创建一个字典来将节点名称映射到其邻居的名称,这使得确定哪些链接显示/隐藏变得容易:
// Set up dictionary of neighbors
var node2neighbors = {};
for (var i =0; i < json.nodes.length; i++){
var name = json.nodes[i].name;
node2neighbors[name] = json.links.filter(function(d){
return d.source.name == name || d.target.name == name;
}).map(function(d){
return d.source.name == name ? d.target.name : d.source.name;
});
}
要获取节点n
的邻居的名称,我首先过滤包含n
的所有链接,然后提取不是n
的节点的名称在每个链接中。
接下来,这是单击节点时执行的逻辑。我正在使用一组节点来跟踪我们想要打开/关闭的节点(OP表示此行为应仅适用于蓝色节点"Node1"
):
var clickableNodes = ["Node1"];
nodes.filter(function(n){ return clickableNodes.indexOf(n.name) != -1; })
// Determine if current node's neighbors and their links are visible
var active = n.active ? false : true // toggle whether node is active
, newOpacity = active ? 0 : 1;
// Extract node's name and the names of its neighbors
var name = n.name
, neighbors = node2neighbors[name];
// Hide the neighbors and their links
for (var i = 0; i < neighbors.length; i++){
d3.select("circle#" + neighbors[i]).style("opacity", newOpacity);
d3.selectAll("line." + neighbors[i]).style("opacity", newOpacity);
}
// Update whether or not the node is active
n.active = active;
});