基于节点度约束d3力布局图

时间:2013-03-12 18:24:36

标签: d3.js force-layout

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

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

能够将单个节点标记为排除(类似于某些节点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' 

运行以下代码以从BEF转到AFT

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

更新2

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

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

1 个答案:

答案 0 :(得分:2)

您可以将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

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