D3力布局图,其中节点位于网格中

kol*_*bok 5 d3.js force-layout

我建立了一个力导向图,但是,对于我来说,我也有一个带有80px * 80px框的网格。我希望图形中的每个节点不仅根据现有的重力和力进行定位,而且还应位于最近的网格框的中间(不固定)。可以在d3js中执行此操作吗?

inf*_*rno 1

你必须应用你的自定义力量

force.on("tick", function() {

  node.attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; });

  link.attr("x1", function(d) { return d.source.x; })
      .attr("y1", function(d) { return d.source.y; })
      .attr("x2", function(d) { return d.target.x; })
      .attr("y2", function(d) { return d.target.y; });

});
Run Code Online (Sandbox Code Playgroud)

所以没有内置的方法来做这样的事情......

因此,在您的情况下,您必须找到靠近的网格盒中心,并使用节点和盒中心之间的距离以及一些重力方程来计算 x 和 y 值。

在你的情况下

node
    .attr("cx", function(d) {
        d.x += f(d).x;
        return d.x;
    })
    .attr("cy", function(d) {
        d.y += f(d).y;
        return d.y;
    });
Run Code Online (Sandbox Code Playgroud)

其中f(d)是重力矢量,取决于盒子中心和实际节点之间的距离d。例如

var blackHole = function (d) {
    var gc = {
        x: 100,
        y: 100
    };
    var k = 0.1;

    var dx = gc.x - d.px;
    var dy = gc.y - d.py;

    return {
        x: k * dx,
        y: k * dy
    };
};
Run Code Online (Sandbox Code Playgroud)

很难找出f(d)真正适用于多个重心的算法,因此我建议您阅读有关此类力的算法。我尝试了一些有趣的例子,但没有一个能按照你想要的方式工作。;-)

现在至少:

var grid = function (d) {
    var fx = d.px % 100;
    if (fx < 0)
        fx += 100;
    if (fx > 50)
        fx -= 100;

    var fy = d.py % 100;
    if (fy < 0)
        fy += 100;
    if (fy > 50)
        fy -= 100;
    var k = -1;

    return {
        x: k * fx,
        y: k * fy
    };
};
Run Code Online (Sandbox Code Playgroud)

这是一个 100px 的密集网格,具有非常简单的力...但我想结果不是您所期望的,节点可以重叠,因为通过强制布局,只有具有公共链接的节点才会相互排斥,至少这是我的经验(编辑:那是因为负电荷)...我认为使用 d3 四边形构建自定义力布局可能会更容易...