【问题标题】:Constraining d3 force layout graphs based on node degree基于节点度约束d3力布局图
【发布时间】:2013-02-28 10:24:12
【问题描述】:

我有一个可能包含大量节点的强制布局,对于图形来说太大而无法响应地呈现。我在想提高系统性能的一种方法是在节点数量太大时通过消除基于入度和出度的节点来修剪图形。

重新计算节点和链接列表有点麻烦,因为链接与节点数组中的索引相关,因此所有链接都需要重新构建。

能够标记单个节点以进行排除似乎更优雅(类似于某些节点fixed 的方式)并让布局算法跳过这些节点。这将允许我动态选择要显示的图形子集,同时为每个节点保留尽可能多的状态(例如位置)。

有没有人实现过类似的东西?

更新

我尝试实施过滤器建议,但遇到了一个有趣的错误。看来filter方法返回的对象没有实现enter

qChart apply limit:2
NODES BEF: [Array[218], enter: function, exit: function, select: function, selectAll: function, attr: function…]
NODES AFT: [Array[210], select: function, selectAll: function, attr: function, classed: function, style: function…]
Uncaught TypeError: Object [object Array] has no method 'enter' 

下面的代码运行得到从BEFAFT

nodeSubset = nodeSubset.filter(function(n) { return (n.sentCount() <= limit); });   

更新 2

我创建了一个jsfiddle 来隔离问题。这个例子实现了我对 ChrisJamesC 答案的解释。当我尝试直接执行他的建议时(将filter 放在data 之后),随后对enter 的调用失败,因为filter 返回的对象没有定义enter

目标是使布局仅选择具有active == true 的那些节点,因此在此示例中,这意味着应排除节点b

【问题讨论】:

    标签: d3.js force-layout


    【解决方案1】:

    您可以将selection.filter() 选项与node.weight 属性结合使用。

    你通常会做的是:

    var node = svg.selectAll(".node")
        .data(graph.nodes)
        .enter().append("circle")
    

    你可以在这里做:

    var node = svg.selectAll(".node")
        .data(graph.nodes)
        .filter(function(d){return d.weight>3})
        .enter();
    

    您可能还必须使用相同的方法从绘制指向这些节点的链接中删除。

    编辑如果您想直接在数据数组中将节点标记为活动,您应该只过滤您提供的数据(并对链接执行相同操作)

    var node = svg.selectAll(".node")
        .data(force.nodes().filter(function(d) { return d.active; }));
    
    var link = svg.selectAll(".link")
          .data(force.links().filter(function(d) { 
              var show =  d.source.active && d.target.active;
              if (show)
                  console.log("kept", d);
              else
                  console.log("excluded", d);
              return show;
          }) );
    

    Fiddle

    如果您想通过计算每个节点的权重来做到这一点,我仍然建议您在将节点和链接传递给图表并将节点标记为活动或不遵循特定条件之前执行此操作,然后过滤链接根据活动节点。否则,您将不得不加载整个力导向布局以获得权重,然后过滤数据以重新加载力导向图。

    【讨论】:

    • 我尝试实施您的建议,但遇到了问题,如问题的编辑所示。基本上,filter() 方法返回的东西没有定义 enter()
    • 对不起。你能构建一个 jsFiddle 吗?
    • 好的,这是有道理的,但这会阻止力布局接触排除的数据对象吗?还是会强制仍然尝试定位它们?
    • 它们将在力布局中,因此将计算它们的位置。
    • 我想这意味着我需要在强制应用过滤器,而不是在 DOM 级别。我正在尝试整理力布局以使其表现更好。