在D3力导向布局中,如何在不拖动的情况下以编程方式定位固定节点?

时间:2014-08-12 17:42:18

标签: javascript d3.js force-layout

this question的答案中,mbostock注意到"如果一个节点是固定的,它只能通过拖动而不是通过模拟来移动。"

如果我想以编程方式定位节点,或者通过设置d.x和d.y值,该怎么办?到目前为止,我的尝试失败了。我尝试了d.x和d.y的明显设置,但固定节点会忽略这些值。我还试图暂时"取消修复",重绘,然后"重新修复"节点,但这也不起作用 - 节点在下一个节拍时神奇地重置到它们的原始位置。

这是后一种方法的running example

这是该代码的关键位,在点击时执行:

function explicitlyPosition() {
  node.each(function(d) {
    d.x = 0;
    d.y = 0;
    d.fixed = false;
  });
  tick();
  node.each(function(d) {
    d.fixed = true;
  });
  force.resume();
}

有没有办法使用我尝试过的方法或类似的方法来做到这一点?或者我可以在D3中使用完全不同的图形布局,但我理想地希望我的图形的大部分以强制导向的方式布局。

谢谢!

2 个答案:

答案 0 :(得分:5)

点击tick时,节点的先前位置用于确定新位置,并存储在pxpy属性中。如果您更改这些属性,则运行tick会将xy属性更新为这些值。

Fiddle.

基本上,您的节点会在重绘时神奇地修复新值,而不是神奇地修复到旧值。

答案 1 :(得分:2)

2014年答案中使用的jsfiddles和此问题的评论已经过时了D3版本4.在版本4中,大大简化了制作固定节点的过程。您只需为要修复的每个节点设置fxfy值即可。

例如,像这样:

var graph = {
    "nodes": [
        // unfixed
        {"id":0},
        // fixed
        {"id":1, "fx": 200, "fy": 200},
        {"id":2, "fx": 200, "fy": 300},
        {"id":3, "fx": 300, "fy": 250}
    ],
    "links": [
        {"source": 0, "target": 1},
        {"source": 0, "target": 2},
        {"source": 1, "target": 3},
        {"source": 2, "target": 3}
    ]
};

或者这个:

graph.nodes[3].fx = 500;
graph.nodes[3].fy = 250;

或者这个:

graph.nodes.each(function(d) {
    if(d.id == 2) {
        d.fx = 0;
        d.fy = 0;       
    }
});