2016-08-17 1 views
0

Ich verwende ein D3-Force-Layout und versuche, untergeordnete Knoten zu reduzieren, während das Diagramm fest bleibt, z. indem Sie sie und die Opazität ihrer Links einfach ändern. Ich versuche jedoch nicht, alle Knoten gleichzeitig zu reduzieren - ich habe tatsächlich ein Attribut in jedem Knoten namens "group", das 1,2 oder 3 sein kann.D3 Layout erzwingen: Collapse Untergruppe von untergeordneten Knoten (Opazitätsänderung)

Wenn ich auf einen Knoten klicke, erscheint ein Tooltip mit 3 Schaltflächen für jede dieser Gruppen - wenn ich auf den richtigen Knopf klicke, möchte ich, dass der Kind-Knoten dieses Typs zusammenbricht, aber alle seine Kinder (von allen 3 Gruppen) zusammenfallen.

Hier ist die fiddle.

Ich habe bisher versucht Anordnungen der Knoten Gruppen-IDs und entsprechenden Verbindungs-IDs zu erstellen und dann JQuery verwenden, um die DOM-Objekte zu verstecken, aber das hat nicht funktioniert:

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

Weiß jemand, wie man am besten um dies zu tun?

Danke.

Antwort

1

Wenn es nur die Opazität ist, die Sie ändern möchten, ist das ziemlich einfach. Ich denke, wenn Sie einen Knoten Kinder verstecken Sie die Kinder ihrer Kinder und so weiter verstecken möchten?

Zuerst setze ich eine Variable d.hiddenNode. So kann ich die Deckkraft umschalten. Ich setze es auf falsch. Und dann auf Klick-Funktion:

.on('click', function(d) { 
    console.log(d); 
    if(d.hiddenNode){ 
     hideChildren(d, false); 
     d.hiddenNode = false; 
    } else { 
     hideChildren(d, true); 
     d.hiddenNode = true; 
    } 

    }) 

Jetzt, da Sie die Kinder Kinder etc wollen versteckt werden müssen Sie eine rekursive Funktion wie so. Eine, die Verbindungen und Knoten versteckt (ich habe zu erklären, kommentiert):

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

Hier ist die aktualisierte Geige: http://jsfiddle.net/thatOneGuy/3g4fqfa8/2/

EDIT

Für die Pop-up-i gerade einen div, dass die 3 enthält Gruppen, 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 dies in CSS versteckt:

.group{ 
    width: 50px; 
    height:50px; 
    border : 1px solid black; 
} 

#groupChoice{ 
    visibility:hidden; 
} 

Ich habe die Logik leicht geändert, aber dies ist die aktualisierte Geige mit Kommentaren: http://jsfiddle.net/thatOneGuy/3g4fqfa8/3/

Theres einige Arbeit, die mit den Links getan werden muss. Ich habe nicht genug Zeit atm, um es zu beenden, es tut mir leid. Aber das sollte dich beginnen.

Grundsätzlich, wenn Sie auf einen Knoten klicken, erscheint Pop-Up, Sie wählen eine Gruppe aus, die versteckt werden soll. Treffen Sie den gleichen Knoten erneut, wählen Sie einen Knoten aus, der angezeigt werden soll. Dies wurde sehr schnell gemacht, also ist vieles falsch, aber die Grundlagen sind das, so sollte es helfen :)

+0

Es tut mir leid, ich habe nicht genug Zeit, um es zu beenden. Die Logik ist ziemlich einfach, überprüfen Sie einfach, ob der Knoten zu der Gruppe gehört, die Sie verstecken möchten, und wenn es ist, verstecken Sie es und seine Kinder – thatOneGuy

+1

Vielen Dank! – annikam

Verwandte Themen