这两天学习了使用Path绘制贝塞尔曲线相关,然后自己动手做了一个类似QQ未读消息可拖拽的小气泡,效果图如下:
接下来一步一步的实现整个过程。
基本原理
其实就是使用Path绘制三点的二次方贝塞尔曲线来完成那个妖娆的曲线的。然后根据触摸点不断绘制对应的圆形,根据距离的改变改变原始固定圆形的半径大小。最后就是松手后返回或者爆裂的实现。
Path介绍:
顾名思义,就是一个路径的意思,Path里面有很多的方法,本次设计主要用到的相关方法有
moveTo()
移动Path到一个指定的点
quadTo()
绘制二次贝塞尔曲线,接收两个点,第一个是控制弧度的点,第二个是终点。
lineTo()
就是连线
close()
闭合Path路径,
reset()
重置Path的相关设置
- Path入门热身:
1 2 3 4 5 6 7 8 9 10 |
path.reset(); path.moveTo(200, 200); //第一个坐标是对应的控制的坐标,第二个坐标是终点坐标 path.quadTo(400, 250, 600, 200); canvas.drawPath(path, paint); canvas.translate(0, 200); //调用close,就会首尾闭合连接 path.close(); canvas.drawPath(path, paint); |
记得不要在onDraw方法中new Path
或者 Paint
哟!
具体实现拆分:
其实整个过程就是绘制了两个贝塞尔二次曲线的的闭合Path路径,然后在上面添加两个圆形。
- 闭合的
Path
路径实现从左上点画二次贝塞尔曲线到左下点,左下点连线到右下点,右下点二次贝塞尔曲线到右上点,最后闭合一下!! - 相关坐标的确定
这是这次里面的难点之一,因为涉及到了数学里面的一个sin,cos,tan等等,我其实也忘完了,然后又脑补了一下,废话不多说,直接上图!!
为什么自己要亲自去画一下呢,因为画了你才知道,在360旋转的过程中,角标体系是有两套的,如果就使用一套来画的话,就画出现在旋转的过程中曲线重叠在一起的情况!
问题已经抛出来了,接下来直接看看代码实现!
角度确定
根据贴出来的原理图可以知道,我们可以使用起始圆心坐标和拖拽的圆心坐标,根据反正切函数来得到具体的弧度。
1 2 3 |
int dy = Math.abs(CIRCLEY - startY); int dx = Math.abs(CIRCLEX - startX); angle = Math.atan(dy * 1.0 / dx); |
ok,这里的startX,Y就是移动过程中的坐标。angle就是得到的对应的弧度(角度)。
相关Path绘制
前面已经提到在旋转的过程中有两套坐标体系,一开始我也很纠结这个坐标体系要怎么确定,后面又恍然大悟,其实相当于就是一三象限正比例增长,二四象限,反比例增长。
1 2 |
flag = (startY - CIRCLEY ) * (startX- CIRCLEX ) <= 0; //增加一个flag,用于判断使用哪种坐标体系。 |
最最重要的来了,绘制相关的Path路径!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
path.reset(); if (flag) { //第一个点 path.moveTo((float) (CIRCLEX - Math.sin(angle) * ORIGIN_RADIO), (float) (CIRCLEY - Math.cos(angle) * ORIGIN_RADIO)); path.quadTo((float) ((startX + CIRCLEX) * 0.5), (float) ((startY + CIRCLEY) * 0.5), (float) (startX - Math.sin(angle) * DRAG_RADIO), (float) (startY - Math.cos(angle) * DRAG_RADIO)); path.lineTo((float) (startX + Math.sin(angle) * DRAG_RADIO), (float) (startY + Math.cos(angle) * DRAG_RADIO)); path.quadTo((float) ((startX + CIRCLEX) * 0.5), (float) ((startY + CIRCLEY) * 0.5), (float) (CIRCLEX + Math.sin(angle) * CIRCLEX + Math.sin(angle) * Ts2gw1f75w94asd0g30an0gzx2p.gif">
最终效果图
接下来一步一步的实现整个过程。 基本原理其实就是使用Path绘制三点的二次方贝塞尔曲线来完成那个妖娆的曲线的。然后根据触摸点不断绘制对应的圆形,根据距离的改变改变原始固定圆形的半径大小。最后就是松手后返回或者爆裂的实现。 Path介绍:顾名思义,就是一个路径的意思,Path里面有很多的方法,本次设计主要用到的相关方法有
记得不要在onDraw方法中new Path
具体实现拆分:其实整个过程就是绘制了两个贝塞尔二次曲线的的闭合Path路径,然后在上面添加两个圆形。 原理图1
原理图2
为什么自己要亲自去画一下呢,因为画了你才知道,在360旋转的过程中,角标体系是有两套的,如果就使用一套来画的话,就画出现在旋转的过程中曲线重叠在一起的情况! 问题已经抛出来了,接下来直接看看代码实现! 角度确定根据贴出来的原理图可以知道,我们可以使用起始圆心坐标和拖拽的圆心坐标,根据反正切函数来得到具体的弧度。
ok,这里的startX,Y就是移动过程中的坐标。angle就是得到的对应的弧度(角度)。 相关Path绘制前面已经提到在旋转的过程中有两套坐标体系,一开始我也很纠结这个坐标体系要怎么确定,后面又恍然大悟,其实相当于就是一三象限正比例增长,二四象限,反比例增长。
最最重要的来了,绘制相关的Path路径!
|