可折叠Sankey图-D3

问题描述:

我想知道如何使基于鼠标点击的sankey图折叠/展开节点。可折叠Sankey图-D3

我的图是这样的:https://bl.ocks.org/TheBiro/f73a2a0625bb803179f3905fe7624e22

例如,我想点击节点“PAGOU”,所有后续的链路和节点(上右)被取消了。 我根据Vasco Asturiano(参考readme.md)中的颜色选项制作了它。

我适应从我以前的答案在这里下面的代码: Collapsible D3 force directed graph with non-tree data

在小提琴这里

完整代码:https://jsfiddle.net/sheilak/jfwkx4f3/

我添加的属性到节点来跟踪他们是否倒塌,有多少他们的父节点被折叠。此外,无论它们是否可折叠 - 源节点不应该是可折叠的,因为该库似乎不喜欢没有链接的图形。

graph.nodes.forEach(function (d, i) { 
    graph.nodes[i] = { "name": d }; 
    graph.nodes[i].collapsing = 0; // count of collapsed parent nodes 
    graph.nodes[i].collapsed = false; 
    graph.nodes[i].collapsible = false; 
}); 

我改变了链接的代码,指向整个源或目标节点而不是索引,因为我们需要源节点进行过滤。我还设置了所有目标节点都可折叠。

graph.links.forEach(function(e) { 
    e.source = graph.nodes.filter(function(n) { 
     return n.name === e.source; 
     })[0], 
    e.target = graph.nodes.filter(function(n) { 
     return n.name === e.target; 
     })[0]; 
    e.target.collapsible = true; 
}); 

我把布局代码拉出来放到一个函数中,这样我们就可以在每次单击节点时调用它。我还添加了代码,根据每个图表节点和链接是否折叠来过滤图形节点和链接。

update(); 

var nodes, links; 

function update() { 
    nodes = graph.nodes.filter(function(d) { 
    // return nodes with no collapsed parent nodes 
    return d.collapsing == 0; 
    }); 

    links = graph.links.filter(function(d) { 
    // return only links where source and target are visible 
    return d.source.collapsing == 0 && d.target.collapsing == 0; 
    }); 

    // Sankey properties 
    sankey 
    .nodes(nodes) 
    .links(links) 
    .layout(32); 

    // I need to call the function that renders the sakey, remove and call it again, or the gradient coloring doesn't apply (I don't know why) 
    sankeyGen(); 
    svg.selectAll("g").remove(); 
    sankey.align("left").layout(32); 
    sankeyGen(); 
} 

我不得不注释掉这一行,因为它是与单击处理程序的干扰,我不知道我已经改变了那里。

.on("start", function() { 
    //this.parentNode.appendChild(this); 
}) 

我添加了一个点击处理程序来执行折叠。

node.on('click', click); 
function click(d) { 
    if (d3.event.defaultPrevented) return; 
    if (d.collapsible) { 
    // If it was visible, it will become collapsed so we should decrement child nodes count 
    // If it was collapsed, it will become visible so we should increment child nodes count 
    var inc = d.collapsed ? -1 : 1; 
    recurse(d); 

    function recurse(sourceNode){ 
     //check if link is from this node, and if so, collapse 
     graph.links.forEach(function(l) { 
     if (l.source.name === sourceNode.name){ 
      l.target.collapsing += inc; 
      recurse(l.target); 
     } 
     }); 
    } 
    d.collapsed = !d.collapsed; // toggle state of node 
    }  
    update(); 
} 
+1

我觉得这样是因为我没有办法足够感谢你!我非常感谢你的工作来回答这个问题。我试过但我做不到,你的回答对我来说是一个巨大的教训!谢谢。 – TheBiro

上面的提琴很适合每个孩子都有单亲的标准树。然而,对于传统的sankey非常适合的多种血统('格子')场景,这个可折叠的表示可能不太直截了当。例如,当展开节点A以显示其子节点时,如果任何A的子节点具有其他未扩展的父节点,则父节点会自动扩展。这可能是你想要的,因为只显示部分血统会导致误导,但无论如何它确实会让你感到有点意外。迷失方向可以通过不重新居中节点来缓解。可能会出现意想不到的组合扩展效应,特别是对于高度网格化的数据结构。