[英]D3 Force Layout: Collapse Subset of Child Nodes (Opacity Change)
I am using a D3 force layout and trying to collapse child nodes whilst keeping the graph fixed, eg by simply changing them and their links' opacity. 我正在使用D3强制布局,并尝试折叠子节点,同时保持图形固定,例如通过简单地更改它们及其链接的不透明度。 However, I am not trying to just collapse all nodes at once - I actually have an attribute in each node called "group", which can be 1,2 or 3.
但是,我并不是想立即折叠所有节点-实际上,每个节点中都有一个名为“ group”的属性,该属性可以为1,2或3。
When I click on a node, a tooltip appears with 3 buttons for each of these groups - upon clicking on the correct button, I would like the child node of that type to collapse, but all of its children (of all 3 groups) to collapse as well. 当我单击一个节点时,将为每个组显示一个带有3个按钮的工具提示-单击正确的按钮后,我希望该类型的子节点折叠,但其所有3个组的所有子节点都将折叠也会崩溃
I have so far tried to create arrays of the node group ids and corresponding link IDs, and then use JQuery to hide those DOM objects but this didn't work: 到目前为止,我已经尝试创建节点组ID和对应的链接ID的数组,然后使用JQuery隐藏那些DOM对象,但这没有用:
function collapseNodes(node, collapseType, isCollapsed) {
var collapseData = minimise(node, collapseType);
var cNodes = collapseData.nodes,
cLinks = collapseData.links;
console.log(collapseData);
var newClass = isCollapsed ? "uncollapsed" : "collapsed";
cNodes.forEach(function(n) {
d3.select(n).style("opacity", 0);
});
cLinks.forEach(function(l) {
d3.select(l).style("opacity", 0);
});
}
function minimise(node, assetMinType = "") {
// Function to minimise a node
var minNodes = [];
var minLinks = [];
if (node.group == 'asset') {
node.children.forEach(function(child) {
if (child.group == assetMinType)
minimiseRec(child, node.id);
});
}
else {
minimiseRec(node, "");
// We want to keep the top node and link
minNodes.shift();
minLinks.shift();
}
function minimiseRec(node, parentID) {
minNodes.push("#" + node.id);
minLinks.push("#parent_" + parentID + "_child_" + node.address);
node.children.map(function(child) {
minimise(child, node.id);
});
}
return { nodes: minNodes, links: minLinks };
}
Does anyone know how best to do this? 有谁知道如何做到最好?
Thanks. 谢谢。
If its only the opacity you wish to change this is fairly simple. 如果您只是想改变它的不透明度,那将非常简单。 I guess if you hide a nodes children you want to hide their childrens children and so on ?
我想如果您隐藏节点的孩子,您想隐藏其孩子的孩子,依此类推?
First I set a variable d.hiddenNode
. 首先,我设置一个变量
d.hiddenNode
。 This is so I can toggle the opacity. 这样我就可以切换不透明度。 I set it to false.
我将其设置为false。 And then on click function :
然后点击功能:
.on('click', function(d) {
console.log(d);
if(d.hiddenNode){
hideChildren(d, false);
d.hiddenNode = false;
} else {
hideChildren(d, true);
d.hiddenNode = true;
}
})
Now because you want the childrens children etc to be hidden you need a recursive function like so. 现在,因为您希望隐藏孩子的孩子等,因此需要像这样的递归函数。 One that hides links and nodes ( I have commented to explain) :
隐藏链接和节点的一种(我已评论解释):
function hideChildren(node, hide) {
for (var i = 0; i < node.children.length; i++) {
recurseChildren(node.children[i]); //loop through children to hide
}
function recurseChildren(node) {
nodeEnter.each(function(d) { //go through all nodes to check for children
if (d.index == node.index) { //if child is found
d3.select(this).style('opacity', function(){
return hide ? 0 : 1; //toggle opacity depending on d.hiddenNode value
}) //.remove();
}
})
link.each(function(d) { //same with links
if (d.source.index == node.index || d.target.index == node.index ) { //if source or target are hidden hide the link
d3.select(this).style('opacity', function(){
return hide ? 0 : 1;
}) //.remove();
}
})
if (node.children) { //if this node has children, call again but with their children
for (var i = 0; i < node.children.length; i++) {
recurseChildren(node.children[i]);
}
}
}
}
Here is the updated fiddle : http://jsfiddle.net/thatOneGuy/3g4fqfa8/2/ 这是更新的小提琴: http : //jsfiddle.net/thatOneGuy/3g4fqfa8/2/
EDIT 编辑
For the pop up i just created a div that contains the 3 groups, 1,2,3 : 对于弹出窗口,我刚刚创建了一个div,其中包含3、1、2、3组:
<div id='groupChoice'>
<div id='group1' class = 'group' onclick='hideGroup(1)'>1</div>
<div id='group2' class = 'group' onclick='hideGroup(2)'>2</div>
<div id='group3' class = 'group' onclick='hideGroup(3)'>3</div>
</div>
Set this to hidden in CSS : 将此设置为隐藏在CSS中:
.group{
width: 50px;
height:50px;
border : 1px solid black;
}
#groupChoice{
visibility:hidden;
}
I have changed the logic slightly but this is the updated fiddle with commentary : http://jsfiddle.net/thatOneGuy/3g4fqfa8/3/ 我已略微更改了逻辑,但这是带有注释的更新小提琴: http : //jsfiddle.net/thatOneGuy/3g4fqfa8/3/
Theres some work that needs to be done with the links. 链接需要完成一些工作。 I havent got enough time atm to finish it off, im sorry.
我没有足够的时间来完成它,对不起。 But that should get you started.
但这应该可以帮助您入门。
Basically, when you click a node, pop up comes up, you chose a group to hide, they get hidden. 基本上,当您单击一个节点时,会弹出一个弹出窗口,您选择了一个要隐藏的组,它们被隐藏了。 Hit the same node again, chose a node to show.
再次点击同一节点,选择要显示的节点。 This was done super quick, so there's a lot wrong with it, but the basics are the so it should help :)
这是非常快地完成的,所以有很多问题,但是基本知识应该可以帮助:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.