单击D3 Javascript中的节点时如何显示和隐藏链接和节点

use*_*315 4 javascript css d3.js force-layout

我试图按照这个D3 Javascript链接:> http://bl.ocks.org/mbostock/1093130来了解click事件的工作原理.不幸的是,我无法完全理解整个代码.我现在要做的是点击蓝色节点时,将显示另外两个节点及其链接.当我再次单击同一节点时,两个节点及其链接必须隐藏.如果我点击其他两个节点中的一个节点,则不会发生任何事情.

这是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
    }
]
}
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

<!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>
Run Code Online (Sandbox Code Playgroud)

请有人帮我解决这个问题.非常感谢您的协助.

mdm*_*dml 10

您可以通过单击该节点来分解打开/关闭节点的邻居/边缘的可见性所需的步骤,如下所示:

  1. 您需要根据源/目标的名称对链接进行分类,并根据名称给出节点ID.这使得确定哪些节点/链接切换是微不足道的.
  2. 您需要存储每个节点当前是否处于"活动状态",您可以使用它来确定是否应隐藏/显示节点的邻居.
  3. 您需要为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;
        });
}
Run Code Online (Sandbox Code Playgroud)

为了获取节点的邻居的名称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;
    });
Run Code Online (Sandbox Code Playgroud)