在D3中移动固定节点 [英] Moving fixed nodes in D3
问题描述
我有一个D3强制导向布局中的节点设置为 fixed = true。如果我设置了.x或.y值,节点本身不会移动到新位置。
I have nodes in a D3 force-directed layout that are set to .fixed = true. If I set the .x or .y values, the nodes themselves don't move to their new position.
这是我的函数:
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;
}
}
}
}
strong> UPDATE 1:
UPDATE 1:
这里是基于Jason的建议的工作功能:
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();
}
推荐答案
与实际渲染脱钩。通常你有一个tick处理程序,它会更新布局算法的每个tick的SVG元素的属性(关于解耦的好处是你渲染到< canvas>
而不是其他)。
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).
因此,为了回答你的问题,你只需要直接调用这个处理程序为了更新你的SVG元素的属性。例如,您的代码可能如下所示:
So to answer your question, you simply need to call this handler directly in order to update the attributes of your SVG elements. 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; });
}
所以你可以简单地调用 code>在任何时候更新元素位置。
So you could simply call tick()
at any point and update the element positions.
你可能会试着调用 force.tick $ c>,但是这意味着用作
force.start()
的同步替代:可以重复调用它,每个调用执行布局算法的步骤。但是,有一个内部 alpha
变量用于控制内部使用的模拟退火,并且一旦布局冷却,该变量将 0
并进一步调用 force .tick()
将没有效果。 (不可否认,如果 force.tick()
总是触发一个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. 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. (Admittedly it might be nice if force.tick()
always fired a tick event regardless of cooling, but that is not the current behaviour).
正如你在注释中指出的,如果手动设置 dx
和 dy
您还应该设置具有相同值的 d.px
和 d.py
,如果您希望节点保留在某一位置。
As you correctly noted in the comments, if you manually set d.x
and d.y
, you should also set d.px
and d.py
with the same values if you want the node to remain in a certain position.
这篇关于在D3中移动固定节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!