让 d3.forceCollide() 的两个实例一起玩得很好

Make two instances of d3.forceCollide() play nice together

我想要 d3.forceCollide() 的两个实例。在一种情况下,每个节点都被推离彼此以防止重叠。在第二个中,只有一部分节点被推开,半径更大。

为了完成第二个力,我调整了初始化方法来过滤传入节点,如下所示:

function selective(force,filter){
    var init = force.initialize;
    force.initialize = function(_){return init(_.filter(filter));};
    return force;
}

var dpi = 90;  // approximate pixels per inch in SVG
var size = dpi * (1/4); // quarter-inch unit size

var universally_applied = 
    d3.forceCollide()
    .radius(size)
    .strength(1);

var selectively_applied =
        selective(
            d3.forceCollide(),
            function(d){return d.id === color;}
        )
        .radius(size*5)
        .strength(1);
}

现在,这几乎行得通了。我创建了一个 fiddle 来查看它的实际效果:https://jsfiddle.net/jarrowwx/0dax43ue/38/ - 每个彩色圆圈应该从远处排斥所有其他相同颜色的圆圈。每一种其他颜色,它只是撞到并将它推开。

如果我不更改定义事物的顺序,则选择性施加的力仅应用于第一种颜色(红色)。如果我在施加力之前打乱 data 数组,则很难准确定义会发生什么,但是力会应用于某些圆圈而不是大多数其他圆圈,即使是相同颜色的圆圈也是如此。

知道这里发生了什么,或者如何解决它吗?

D3 团队认为此行为是一个错误 (Isolating forces to a subset of nodes? #72),并将其修复。该修复包含在 d3-force 的 1.0.4 版中,从 4.4.0 版开始作为完整 D3 构建的一部分提供。

问题已使用 "Partial forces on nodes in D3.js" 建议的解决方案解决,代码现在按预期工作。