Skip to main content
 首页 » 编程设计

d3.js之如何在 D3.js 中制作多个组网络节点的凸包

2024年02月13日15mq0036

我正在尝试制作网络图,其中节点按属性分组,并且它们通过位置(强制布局)并使用凸包按组捆绑。喜欢this但无需单击即可折叠/展开。该模型/代码对于初学者来说有点太复杂,无法剖析和学习。

我的问题可以简单地说:是否有网络+分组功能的示例代码,包括节点在多个组中的可能性?

有时一组中只有一个节点,而基本凸包对于少于三个节点不起作用。上面的示例对此有一个修复(我不明白), this one 也是如此。这会创建不可见的节点并且可能更容易。

组可以嵌套在多层中。 This tutorial提供使用 d3.nest() 获取层次结构中的数据所需的所有信息。但它可能不是一个层次结构,一个节点可能位于多个组中,并且需要位于正确的外壳和位置中。有些节点不会属于任何组,但仍会在网络中连接。

我知道力布局中的力是相加的,因此让组和链接以简单的方式影响节点位置应该不是问题,但我还没有看到这样的简单示例。我的方法是向多焦点示例添加网络连接,看看是否可以使其工作。

作为奖励,节点不应重叠,对于分层元素,基础层节点应围绕一个圆圈放置,以便多个组中的节点位于这些组之间 like this 。我现在提到这些是因为对这些功能的渴望可能会影响上述需求的最佳解决方案。

我将从this JSFiddle开始 build 这座建筑。 ;随着我自己在代码上取得进展,我将继续更新和完善这个问题。我将不胜感激任何指向比可折叠代码更接近我想要的代码的指针,D3 的限制/问题的警告(例如需要解决 1-2 个节点的凸包),以及提供其中之一的代码以可理解和模块化的方式实现最终目标的能力。真的,我们非常感谢任何帮助。

请您参考如下方法:

虽然这个问题在过去一周没有引起太多关注,但希望答案对某些人有用。我设法为 linkDistance 使用一个函数,该函数一开始很大,然后缩小,具体取决于 (1) 源和目标是否在同一个集合中,以及 (2) 该集合的级别 - 即、组或子组或子子组。

基本的解决方案思想来自only example I could find of this capability 。我实际使用的 linkDistance 函数是一种有点简单的方法,但是它可以很好地完成工作,并且可以轻松地适应许多其他人的许多其他目的(我希望)。根据您的分组,您可能需要通过我在这里使用的函数来调整链接的其他功能(例如颜色)。

force 
    .nodes(graph.nodes) 
    .links(graph.links) 
    .linkDistance(function(thisLink) {  
        var myLength = 100, theSource = thisLink.source, theTarget = thisLink.target; 
        groupNodes.forEach(function(groupList) {  
            if (groupList.indexOf(theSource) >= 0 && groupList.indexOf(theTarget) >= 0) { 
                myLength = myLength * 0.7; 
            } 
        }); 
        subgroupNodes.forEach(function(groupList) {  
            if (groupList.indexOf(theSource) >= 0 && groupList.indexOf(theTarget) >= 0) { 
                myLength = myLength * 0.4; 
            } 
        }); 
        subsubgroupNodes.forEach(function(groupList) {  
            if (groupList.indexOf(theSource) >= 0 && groupList.indexOf(theTarget) >= 0) { 
                myLength = myLength * 0.2; 
            } 
        }); 
        return myLength; } ) 
    .linkStrength(function(l, i) { return 1; } ) 
    .gravity(0.05)    
    .charge(-600)    
    .friction(0.5)   
    .start(); 

此解决方案的一个版本以及其他改进可以在 this JSFiddle 中找到。 。

虽然这通过调整组成员资格的链接力来回答我的问题,但它并没有按照我最初预期的方式组合链接+组的力。我仍然希望能够让子组“渴望”彼此远离,进入角落,但受到连接它们的边缘的限制(而不是强制它们处于圆形布局上)。

请注意,我的组被外部定义为列表的列表。如果您的情况中的组成员身份是节点属性,那么您可以使用 d3.nest() 函数来生成我必须使用映射函数创建的节点组,但我不这样做认为如果小组有重叠的成员,这将会起作用。