简体   繁体   English

在D3中移动固定节点

[英]Moving fixed nodes in D3

I have nodes in a D3 force-directed layout that are set to . 我在D3强制定向布局中设置了节点。 fixed = true. fixed = true。 If I set the .x or .y values, the nodes themselves don't move to their new position. 如果我设置.x或.y值,节点本身不会移动到新位置。

Here's my function: 这是我的功能:

function fixNode(idArray, locationX, locationY) {
    for ( x = 0; x < idArray.length; x++ ) {
        for ( y = 0; y < nodes.length; y++ ) {
            if (nodes[y].id == idArray[x]) {
                nodes[y].fixed = true;
                nodes[y].x = 50;
                nodes[y].y = 50;
                break;
            }
        }
    }
}

UPDATE 1: 更新1:

Here is the working function based on Jason's advice: 这是基于杰森建议的工作函数:

function fixNode(idArray, locationX, locationY) {
    for ( x = 0; x < idArray.length; x++ ) {
        for ( y = 0; y < nodes.length; y++ ) {
            if (nodes[y].id == idArray[x]) {
                nodes[y].fixed = true;
                nodes[y].x = 50;
                nodes[y].y = 50;
                nodes[y].px = 50;
                nodes[y].py = 50;
                break;
            }
        }
    }
    tick();
}

The force-directed layout is decoupled from the actual rendering. 力导向布局与实际渲染分离。 Normally you have a tick handler, which updates the attributes of your SVG elements for every "tick" of the layout algorithm (the nice thing about the decoupling is you render to a <canvas> instead, or something else). 通常你有一个tick处理程序,它可以为布局算法的每个“tick”更新SVG元素的属性(关于解耦的好处是你渲染到<canvas> ,或其他东西)。

So to answer your question, you simply need to call this handler directly in order to update the attributes of your SVG elements. 因此,要回答您的问题,您只需直接调用此处理程序即可更新SVG元素的属性。 For example, your code might look like this: 例如,您的代码可能如下所示:

var node = …; // append circle elements

var force = d3.layout.force()
    .nodes(…)
    .links(…)
    .on("tick", tick)
    .start();

function tick() {
  // Update positions of circle elements.
  node.attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; });
}

So you could simply call tick() at any point and update the element positions. 所以你可以随时调用tick()并更新元素位置。

You might be tempted to call force.tick() , but this is meant to be used as a synchronous alternative to force.start() : you can call it repeatedly and each call executes a step of the layout algorithm. 您可能想要调用force.tick() ,但这可以用作force.start()的同步替代方法:您可以重复调用它,每次调用都会执行布局算法的一个步骤。 However, there is an internal alpha variable used to control the simulated annealing used internally, and once the layout has "cooled", this variable will be 0 and further calls to force.tick() will have no effect. 但是,有一个内部alpha变量用于控制内部使用的模拟退火,一旦布局“冷却”,该变量将为0并且对force.tick()进一步调用将不起作用。 (Admittedly it might be nice if force.tick() always fired a tick event regardless of cooling, but that is not the current behaviour). (不可否认,如果force.tick()总是触发一个tick事件而不管冷却,那可能会很好,但这不是当前行为)。

As you correctly noted in the comments, if you manually set dx and dy , you should also set d.px and d.py with the same values if you want the node to remain in a certain position. 正如您在注释中正确指出的那样,如果手动设置dxdy ,如果希望节点保持在某个位置,还应该将d.pxd.py设置为相同的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM