How to display and hide links and nodes when clicking on a node in D3 Javascript

落爺英雄遲暮 提交于 2019-12-07 11:14:30

问题


I am trying to follow this D3 Javascript link: > http://bl.ocks.org/mbostock/1093130 to understand how the click event works. Unfortunately, I could not fully understand the whole codes. What I am trying to do at the moment is when clicking on the blue node, the other two nodes and their links will display. When I click on the same node again, the two nodes and their links must hide. In case I click on one of the other two nodes, nothing should happen.

Here is the JSON file:

{
"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
    }
]
}

Here is my code:

<!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>

Could anyone please help me solve this issue please. Your assistance would be very much appreciated.


回答1:


You can break down the steps required to toggle on/off the visibility of a node's neighbors/edges by clicking that node as follows:

  1. You need to class links based on the names of the sources/targets, and give nodes ids based on their names. This makes determining which nodes/links to toggle trivial.
  2. You need to store whether or not each node is currently "active," which you can use to determine whether or not you should hide/show the node's neighbors.
  3. You need to add an on("click", function(){ ... }) to each node.

I created a JSFiddle that demonstrates this approach. The main points to highlight are that, first, I create a dictionary to map node names to the names of their neighbors, which makes determining which links to show/hide easy:

// 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;
        });
}

To get the names of the neighbors of a node n, I am first filtering all the links that include n, and then extracting the name of the node that is not n in each of those links.

Next, here's the logic performed when you click on a node. I'm using an array of nodes to keep track of the nodes we want to toggle on/off (the OP said this behavior should only apply for the blue node "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;
    });


来源:https://stackoverflow.com/questions/20249215/how-to-display-and-hide-links-and-nodes-when-clicking-on-a-node-in-d3-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!