I'm trying to do this thing in D3.js but unable to find a way to do it.
What I want to do is, when a person clicks on the root node (level 0), it should show the child elements (level 1). When a person clicks on one of the child nodes (level 1) it should show its childrens (level 2) and the parent and parent-of-parent (level 1, this what the user clicked), but hide all the unrelated parents (from level 1).
Let me explain you this with pictures.
You could do something like http://bl.ocks.org/benlyall/4fea200ebebb273aa4df
I forked http://bl.ocks.org/mbostock/4339083 and made a few changes:
Added a new property to each node .all_children
which keeps track of all children. We need this, or something similar since .children
contains the child nodes currently displayed, and ._children
is used by the existing code to determine if a node contains children or not (and sets the style accordingly).
Also added a .hidden
property that helps to determine whether or not the node should be displayed.
These are added after loading the data:
d3.json("flare.json", function(error, flare) { root = flare; root.x0 = height / 2; root.y0 = 0; function collapse(d) { if (d.children) { d.all_children = d.children; d._children = d.children; d._children.forEach(collapse); d.children = null; d.hidden = true; } } root.all_children = root.children; root.children.forEach(collapse); root.children.forEach(function(d) { d.hidden = false; }); root.hidden = false; update(root); });
Updated the update
function to reflect the new changes and only draw the nodes that are supposed to be drawn:
function update(source) { // Compute the new tree layout. var nodes = tree.nodes(root).filter(function(d) { return !d.hidden; }).reverse(), links = tree.links(nodes);
The nodes
variable is set to only contain nodes that are NOT hidden.
Updated the click
handler to correctly set the state of the nodes in the display:
// Toggle children on click. function click(d) { if (d.children) { d._children = d.children; d.children = null; if (d._children) { d._children.forEach(function(n) { n.hidden = true; }); if (d.parent) { d.parent.children = d.parent.all_children; d.parent.children.forEach(function(n) { n.hidden = false; }); } } } else { d.children = d._children; d._children = null; if (d.children) { d.children.forEach(function(n) { n.hidden = false; }); if (d.parent) { d.parent.children = [d,]; d.parent.children.filter(function(n) { return n !== d; }).forEach(function(n) { n.hidden = true; }); } } } update(d); }
The first part of the if
statement is called when we're collapsing a node, in which case, we need to display all of the siblings of the clicked node by setting d.parent.children
to d.parent.all_children
and setting each of those nodes to .hidden = false
. And we need to hide all the children of the clicked node by setting d.children = null
and then setting each node in d._children
to hidden.
The second part of the if
statement is called when we're expanding a node, in which case, we need to hide its siblings (set .hidden
to true
) and update the .children
property of the clicked node's .parent
node so that only the clicked node is listed as a child.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.