Android绘制类似电脑版qq的箭头

先上最终的效果图:
这里写图片描述
一直忙于画板批注这块,之前随便在网上找了一个箭头的算法,画出来后实际测试了,大家纷纷反馈箭头太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;

分析图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);
    }
  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值