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

匿名 (未验证) 提交于 2019-12-03 08:54:24

问题:

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


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