我正在为android开发思维导图工具。我正在为我的思维导图http://www.examtime.com/files/2013/08/How-to-create-an-online-mind-map.jpg创建这种布局。有没有办法在运行时创建一条这些类型的线(如图中所示)来连接对象。请帮帮忙
发布于 2013-10-22 01:44:03
您应该查看三次bezier曲线(样条线)。要做到这一点,简单地使用画布是不容易的。下面是一个概述:
贝塞尔曲线使用两个点(P0 -原点和P1 -目标)和两个向量(V0 -曲线离开P0的方向,V1 -曲线进入P1的方向)。出于我们的目的,P0、P1、V0、V1都应该是PointF类型。
我们将使用t来表示路径上的位置。当t=0时,位置在P0,当t=1时,位置在P1。在0和1之间的任何t值都将沿着路径。0 <= t <= 1。
现在,作为一个例子,让我们看一下连接"Nobody's perfect“节点和"Tidy up later”节点的曲线。
在这种情况下,P0将是“没有人的完美”的右中间部分,而P1将是“稍后整理”的底部中间部分。
我们将使两个向量垂直于它们离开/进入的节点,因此v0的值将是{P1.x - P0.x,0}。此向量将指向右侧,其强度相当于两个节点之间的距离。以类似的方式,我们将构造指向节点的V1向量:{0,P0.y - P1.y}
现在您有了矢量和点,您将需要开始绘制曲线。为此,您将使用一些可被1整除的小步长值迭代t,例如,0.1,0.025,0.001等。让我们将此值称为"step“。每次迭代都会在曲线上生成一个点,您将希望在这些点之间连接一条直线。
以下是此部分的代码示例:
PointF start, end;
for (float t = 0; t < 1; t += step)
{
start = getBezierPosition(t);
end = getBezierPosition(t + step)
canvas.drawLine(start.x, start.y, end.x, end.y, paint);
}现在,困难的部分-计算位置t处的bezier曲线的位置:
private PointF getBezierPosition(float t)
{
PointF result = new PointF();
float oneMinusT, x, y;
oneMinusT = 1 - t;
x = oneMinusT * oneMinusT * oneMinusT * P0.x +
3 * oneMinusT * oneMinusT * t * V0.x +
3 * oneMinusT * t * t * V1.x +
t * t * t * P1.x;
y = oneMinusT * oneMinusT * oneMinusT * P0.y +
3 * oneMinusT * oneMinusT * t * V0.y +
3 * oneMinusT * t * t * V1.y +
t * t * t * P1.y;
result.set(x, y);
return result;
}这是三次bezier曲线的公式。你可以在here上了解更多。
我将让您实现确定P0和P1的位置以及V0和V1的方向的逻辑(请记住,它们应该始终垂直于它们离开/进入的节点,以获得最佳结果)。您将需要玩弄逻辑来确定P在节点的哪一侧,并且它很可能将链接到您应用于将节点定位在第一位置的逻辑。
此外,为了获得最好的效果,请尝试使用正在绘制的绘画的笔划宽度。
我承认,这个东西有点重数学,可能不在初学者的舒适区,但如果你想实现动态曲线,就像你在那张图中展示的那样,我担心你会弄脏你的手。
祝你好运,伙计!让我知道这一切的结果:)
https://stackoverflow.com/questions/19500118
复制相似问题