先上最终的效果图:
一直忙于画板批注这块,之前随便在网上找了一个箭头的算法,画出来后实际测试了,大家纷纷反馈箭头太TM丑了,.因为大学毕业后,再没有接触过数学之类的东西,刚开始想这个问题时,脑袋简直一团浆糊..回头买本<数学之美>好好看看..
后来在网上找了一下,也没发现有啥靠谱的方法,最后还是我们公司的大神亲自出马,自己绘制一个类似电脑版qq的箭头,记录一下,学习大神的分解,解决问题的思路..
首先我们已知起始点和终止点的坐标,要根据这两个点绘制一个箭头..
画个图分析下根据图形绘制的常识可以分解为下:我们已知点A,B的坐标,求出点C,D,E,F的坐标,连线A,B,C,D,E,F,即可得到我们要的图形.
1,求出外侧的点D与点F
画个图(分析图1)分析下:
我们根据点B与点A的坐标可以求出灰色表示出的角度,代码为Math.atan((endP.y - startP.y) / (endP.x - startP.x));
因为蓝色角度为已知的40度.而Math.atan()实际返回的是一个pi / 2到 -pi /2之间的值.
因此需要将40度转成相应的float,代码为 (float) (40 * Math.PI / 360);
点D的X坐标即为点B的X坐标 - (灰色角减蓝色角的余弦 * 靛色线的长度) , Y坐标 点B的Y坐标 - (灰色角减蓝色角的正弦 * 靛色线的长度)
同理也可获得点F的坐标
2获取内侧的点C和点E
本部分还没有想好如何画的很完美,只是简单的三等分了一下,回头有空研究如何补全
如分析图2所示:
a1X + (a2X - a1X) / 3, a1Y + (a2Y - a1Y) / 3
点C的X = 点D.x + (点F.x - 点D.x) / 3; 点C的Y = 点D.y + (点F.y - 点D.y) / 3
点E的X = 点D.x + (点F.x - 点D.x) / 3 * 2; 点C的Y = 点D.y + (点F.y - 点D.y) / 3 *2;
最后附上Android相关的代码
private static float arrowAngle = (float) (40 * Math.PI / 360);
private static final int arrowLength = 30;
/**
* @param canvas 画板
* @param startP 开始点
* @param endP 结束点
* @param paint 画笔
*/
public static void drawArrow(Canvas canvas, PointF startP, PointF endP, Paint paint) {
float lineAngle = (float) Math.atan((endP.y - startP.y) / (endP.x - startP.x));
Log.e("---->","lineAngle" +lineAngle);
float angleA1 = lineAngle - arrowAngle;
float angleA2 = lineAngle + arrowAngle;
int adjust = (endP.x >= startP.x) ? -1 : 1;
float a1X = (float) (endP.x + adjust * arrowLength * Math.cos(angleA1));
float a1Y = (float) (endP.y + adjust * arrowLength * Math.sin(angleA1));
float a2X = (float) (endP.x + adjust * arrowLength * Math.cos(angleA2));
float a2Y = (float) (endP.y + adjust * arrowLength * Math.sin(angleA2));
PointF _arrowPoint1 = new PointF(a1X, a1Y);
PointF _arrowPoint2 = new PointF(a1X + (a2X - a1X) / 3, a1Y + (a2Y - a1Y) / 3);
PointF _arrowPoint3 = new PointF(a1X + (a2X - a1X) * 2 / 3, a1Y + (a2Y - a1Y) * 2 / 3);
PointF _arrowPoint4 = new PointF(a2X, a2Y);
double minPointDistance = arrowLength * Math.cos(arrowAngle);
PointF[] points;
if (distance(startP, endP) > minPointDistance) {
points = new PointF[]{startP, _arrowPoint2, _arrowPoint1, endP, _arrowPoint4, _arrowPoint3, startP};
} else {
points = new PointF[]{_arrowPoint1, endP, _arrowPoint4, _arrowPoint1};
}
Path path = new Path();
for (int i =0; i < points.length;i++){
if (i == 0){
path.moveTo(points[0].x,points[0].y);
} else {
path.lineTo(points[i].x,points[i].y);
}
}
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
canvas.drawPath(path, paint);
}