如何控制D3力导向图的模拟速度

8

我正在按照这个 d3 force layout 的例子进行操作。

我想控制点飞向聚类的速度。换句话说,我希望有些点需要更长时间才能到达它们的最终位置,而有些点则需要更短的时间。

我尝试添加一个定时器函数来控制每个 tick 的时间,但它没有起作用。

this.force = d3.layout.force()
.on("tick", setTimeout(tick(d), 50));

我需要对此进行帮助。

3个回答

3
不要设置定时器来调用tick函数,这是由力布局自动完成的。
然而,有一些参数可以设置来修改力布局的行为。与您正在尝试做的内容最相关的是以下内容:
  1. .friction()对应于速度衰减的快慢,因此直接控制节点移动的速度。默认值为0.9,如果要使所有内容变慢,请将其设置为较低的值。
  2. .charge()控制节点之间吸引/排斥的强度。这不直接控制速度,但会影响它。
这些参数中,只有后者可以按节点设置。这使得实现您想要的内容有些棘手,因为您必须仔细平衡力量。作为一种开始方法,将要移动得更慢的节点的电荷设置为更接近0应该会有所帮助。

在力导向布局中还有一些其他参数,但我认为在您的特定情况下不会有用(我想到了.linkStrength().linkDistance()),但您仍然可以查看一下。


是的,我需要逐个节点设置速度。是否可以为每个tick迭代添加“延迟”函数?我知道手动调用tick函数是可能的: “force.start(); for (var i = 0; i < n; ++i) force.tick(); force.stop();” - user3145427
不进行黑客攻击的话,无法调整力导向布局。 - Lars Kotthoff
我想到了一个可能的解决方案。我可以手动为每个节点调用tick函数,比如100次,并记录路径。然后我使用定时器函数根据路径重新绘制节点。这样,我就可以控制每个节点的绘制时间。这个方案有意义吗? - user3145427
计时器处理程序是全局的。你唯一能做的就是忽略某些节点的事件。 - Lars Kotthoff

3

我想到了一种可能的解决方法。我可以手动为每个节点调用tick函数,比如100次,并记录路径。然后我使用定时器函数根据路径重新绘制节点。这样,我就可以控制每个节点的绘制时间。这样做有意义吗?


1

更改 setInterval 函数,调整时间间隔。

尝试以下代码:

Fiddle:

 setInterval(function(){
  nodes.push({id: ~~(Math.random() * foci.length)});
  force.start();
  node = node.data(nodes);
  node.enter().append("circle")
      .attr("class", "node")
      .attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; })
      .attr("r", 8)
      .style("fill", function(d) { return fill(d.id); })
      .style("stroke", function(d) { return d3.rgb(fill(d.id)).darker(2); })
      .call(force.drag);
}, 50); //change the intervel time

谢谢!但是你的代码只改变了插入新节点的时间间隔。如果我将间隔改为500,节点仍需要50才能飞到位置,而我需要等待450才能插入另一个节点。相反,我需要改变节点的速度。这意味着每个节点需要500才能飞到它们的位置。 - user3145427

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接