Android UI 篇- 手势月亮动画
###一、应用场景
1.1、先上效果图
一个有创意的亮度动画,通过手势上下滑动控制手机屏幕亮度,动画从太阳(天亮了)变成月亮(夜黑了),非常漂亮屏幕亮度动画!
###二、流程分析
2.1、先上渐变图分析:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WPMlUBjI-1588761551504)(https://upload-images.jianshu.io/upload_images/2788235-fe118838d2981074.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
- 首先需要画一个圆
- 需要画出
A,B
两点之间的向圆心弯曲的弧度,和A,B
本身的圆弧,然后用PorterDuff.Mode.DST_OUT
,去掉和圆重叠的部分,可以得出月亮。那么向圆心弯曲弧度需要用贝塞尔曲线画出,把A,B
两点作为贝塞尔曲线的定点,并取A,B
两点形成的线段的中垂线上的点C
作为控制点,画出月亮的缺角的弧度,如草图下 :
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-54wQTgG5-1588761551506)(https://upload-images.jianshu.io/upload_images/2788235-7ce95a55ed16b501.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
变量之间的关系:
OC ⊥ AB
,A,B
两点是贝塞尔曲线定点,C
点是贝塞尔曲线的控制点。OC = K * AB
,K
是一个经验值目前可以设置为0.43f
(那么C
点可以被解出来),这样的塞尔曲线的弧度比较美观,拟合圆的弧度。
- 问题分解为要求出
A,B
两点的位置,和C
点的位置,A,B
两点一直在变化,A
点跑得比较快,B
点跑得比较慢,需要模拟出两点的位置(在progress ∈[0,1]
的条件下的位置)。A,B
两点的运动轨迹范围如草图下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JLMyChxC-1588761551508)(https://upload-images.jianshu.io/upload_images/2788235-e8d5de48df8a9104.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
A,B
两点同时出发,A->A'
,B->B'
.(逆时针)
A,B
两点可使用PathMeasure.getPosTan(float distance, float pos[], float tan[])
函数接口得出两点的位置,distance
代表的是A
或者B
点距离起点的距离(这个距离可以通过progress
算出),pos[]
代表传入一个非空数组,函数执行完毕后,A或者B 点的坐标会复赋值到pos[]
中。tan[]
代表A
或者B
点的当前的导数,也就当前点切线的斜率(目前本动画无需用上)。分析完毕,代码撸起来。
备注:另外一种思路实现通过两个圆去
DST_OUT
,得出第一个圆剩余的部分也是月亮,但是第二个圆的圆心轨迹函数,和半径变化轨迹函数,想要画出漂亮的月亮,两个运动轨迹没有规律可言,也很难被求出,只能适用于画静态的月亮,画不了动态的月