我一直在使用力量布局作为我制作的棋盘游戏的物理引擎,并且它一直运作良好。但是,我一直试图弄清楚是否有可能围绕特定焦点旋转节点。考虑一下codepen。我想让codepen中的3个绿色节点以统一的方式围绕焦点旋转。在tick()函数中,我执行以下操作:
var k = .1 * e.alpha;
// Push nodes toward their designated focus.
nodes.forEach(function(o, i) {
o.y += (foci[o.id].y - o.y) * k;
o.x += (foci[o.id].x - o.x) * k;
});
与将节点推向焦点的方式相同,我想将指定为焦点的所有节点围绕所述焦点旋转。有没有办法通过操作tick()函数中的o.y
和o.x
变量来实现这一目的?我曾尝试使用this formula手动设置x和y值,但我认为力布局的电荷和重力可能会使它变得混乱。有什么想法吗?
我知道我使用强制布局来做它不太想做的事情,但任何帮助都会受到赞赏。
答案 0 :(得分:2)
我已经搞乱了你的代码,以获得一个点的基本动作。
我将foci var更改为只有两点的对象:
foci = {
x: 300,
y: 100
};
我添加了数据,你必须给每个节点一个起点:
nodes.push({
id: 0,
x:20,
y:30
});
nodes.push({
id: 0,
x:40,
y:60
});
nodes.push({
id: 0,
x:80,
y:10
});
我为每个节点添加了一个角度,以便您以后可以单独使用它们:
.attr("cx", function(d) {
d.angle = 0; //added
return d.x;
})
并更改了勾号,以便每个节点围绕焦点移动。如前所述,我添加了一个角度,因为这些点将围绕具有不同尺寸半径的不同圆圈移动,因为它们距离焦点点的距离不同。如果你使用一个角度,那么所有节点都将在彼此的顶部移动,这是毫无意义的:
圆上点的公式:
//c = centre point, r = radius, a = angle
x = cx + r * cos(a)
y = cy + r * sin(a)
在勾选中使用:
var radius = 100; //made up radius
node
.attr("cx", function(d) {
if(d.angle>(2*Math.PI)){ restart at full circle
d.angle=0;
}
d.x = foci.x + radius *Math.cos(d.angle) //move x
return d.x;
})
.attr("cy", function(d) {
d.y = foci.y + radius *Math.sin(d.angle) //move y
return d.y;
});
更新了小提琴:https://jsfiddle.net/reko91/yg0rs4xc/7/
这应该很容易实现从圆圈运动变为椭圆运动:))
再看一遍,这只会在一半左右。这是由于滴答功能仅持续几秒钟。如果单击其中一个节点,它将围绕圆圈继续。如果你想要连续发生这种情况,你必须设置一个计时器功能,这样它就会绕着圆圈不停地运行,但这应该很容易实现。
而不是使用滴答功能只需在内部使用定时器创建另一个函数,在加载时调用它并且它将连续运行:)