在d3力导向网络中设置初始位置后的NaN节点位置

时间:2014-10-20 22:47:43

标签: javascript d3.js force-layout

我在D3中创建一个强制定向网络,其中每个节点代表一个集合中的网页,它们之间的有向链接代表从一个网页到另一个网页的超链接。当用户在网页之间移动时,链接将添加到网络中。集合中的节点/网页数量不会发生变化。

每当添加新链接时,我重新加载网络,读取包含新旧链接和所有节点的JSON代码。目前,我正试图平静"此网络的初始加载使得节点不会在随机位置创建,从而可能创建一个网络,其中节点远离它们之前的位置。为此,我想将每个节点的初始位置设置为前一个网络中的位置。

我已通过设置节点的x和y属性来完成此操作,如以下代码段所示:

var links = data.links;
var nodes = data.nodes;

var nodeDictionary = new Object();
if (node != 0) {
    force.stop();

    node.each(function(d) {
        var pos = [];
        var thisNode = d3.select(this);
        pos[0] = thisNode.attr("x");
        pos[1] = thisNode.attr("y");
        var page = thisNode.attr("page");
        nodeDictionary[page] = pos;
    });

    nodes.forEach(function(node) {
        var x = nodeDictionary[node.id][0];
        var y = nodeDictionary[node.id][1];

        //node.px = undefined;
        //node.py = undefined;
        node.x = x;
        node.y = y;
    });
}

这似乎在某些时候或某些节点有效,但大多数情况下这导致节点具有NaN位置。具体来说,这些位置是网络的tick()方法中的NaN,如下所示:

// Animates the force-directed network
function tick() {
    node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
    link.attr("d", drawCurve);
}

function drawCurve(d) {
    var testing = "M" + d.source.x + "," + d.source.y + "L" + d.target.x + "," + d.target.y;
    return testing
}

在其他示例中,我已经看到在强制定向网络中设置初始节点位置的位置,tick()方法看起来更像是这样:

force.on("tick", function() {
    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; });

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

我需要做些什么才能使我的代码使用translate函数吗?我已经尝试在创建新网络之前停止tick方法,如此线程https://groups.google.com/forum/#!topic/d3-js/k6VSYZfMjGA中所建议的那样,但这并没有帮助。在生成新网络之前,是否需要清除某些变量或元素?我还尝试使用各种值组合设置px和py属性以及px,py,x和y属性,但没有成功。

我创建了一个基本代码的jsfiddle,显示了我在这里遇到的问题:http://jsfiddle.net/ew5qprhe/1/ 双击任何节点将导致生成新网络。某些节点已正确设置为其先前位置,但具有NaN位置的节点将移至左上角。

1 个答案:

答案 0 :(得分:2)

关键是改变这项业务:

node.each(function(d) {
    var pos = [];
    var thisNode = d3.select(this);
    pos[0] = thisNode.attr("x");
    pos[1] = thisNode.attr("y");
    var page = thisNode.attr("page");
    nodeDictionary[page] = pos;
});

到此:

node.each(function(d) {
    pos = [];
    pos[0] = d.x;
    pos[1] = d.y;
    var page = d.id;
    nodeDictionary[page] = pos;
});

由于我使用了.attr(“x”)和.attr(“y”),所以发生了奇怪的事情。另外,诅咒我对D3的不熟悉!