用一条线连接两个圆圈(带有DOM元素)

时间:2015-01-24 14:41:37

标签: javascript math graphics geometry famo.us

我正在努力用一条线连接两个圆圈。我正在使用famo.us库。

DEMO on Codepen

a.k.a。 “两个球,一条线。”


问题

线条的角度和长度是正确的,但位置错误


首次尝试

重要的部分应该是第114-116行

connection.origin = [.5, .5];
connection.align = [.5, .5];
connection.body.setPosition([
    Math.min(sourcePos.x, targetPos.x),
    Math.min(sourcePos.y, targetPos.y)
]);

显然我在做数学上的错误。使用这些值可以得到各种结果,但没有什么是正确的。


预期解决方案

(1)最小的解决方案是将圆心与线连接起来。

(2)更好的解决方案是只接触两个圆的表面而不是到达中心的线。

(3)理想的解决方案是在线的每一端都有箭头,看起来像有向图。

1 个答案:

答案 0 :(得分:2)

这解决了它:

connection.body.setPosition([
    sourcePos.x * Math.cos(angle) + sourcePos.y * Math.sin(angle),
    sourcePos.x * Math.sin(-angle)+ sourcePos.y * Math.cos(angle)
]);
  • 您的细分受众群是由source中的偏离以及与target的角度和距离来定义的,因此您必须将其来源设置为source
  • 的来源
  • 旋转似乎不仅会旋转对象,还会旋转原点周围的坐标,因此我将它们旋转-angle进行补偿。

可能有更多的famo.us esque方式(可能你可以在设置位置之前让它旋转,或者让位置为0,0并在转换中添加坐标作为转换)


为了获得更好的解决方案,仍然主要是数学,你可以保持相同的代码,但

  • r source球的半径,将[r * distX / distance, r * distY / distance]移至段的坐标,使其与球的外部接触
  • 从距离
  • 移除两个球的半径

有了这个,我们得到:

var distX = sourcePos.x - targetPos.x;
var distY = sourcePos.y - targetPos.y;
var norm = Math.sqrt(distX * distX + distY * distY);
var distance = norm - (source.size[0]+target.size[0])/2;
var angle = -Math.atan2(-distY, distX);
connection.angle = angle;
connection.size = [distance, 2, 0];
connection.align = [.5, .5];
connection.origin = [.5, .5];
var posX = sourcePos.x - source.size[0]/2 * (distX / norm);
var posY = sourcePos.y - source.size[0]/2 * (distY / norm);
connection.body.setPosition([
  posX * Math.cos(angle) + posY * Math.sin(angle),
  posX * Math.sin(-angle)+ posY * Math.cos(angle)
]);

结果在这个分叉上:http://codepen.io/anon/pen/qEjPLg

我认为当球快速时线长度关闭的事实是一个时间问题。最有可能的是,当球的中心尚未针对该帧进行更新时,您可以计算线段的长度和位置。