之前在一篇文章里面使用过多根贝塞尔曲线做了一个比较酷炫的动效,那会就觉得那种思路挺有趣的,感觉可以顺着这种思路完成一个更加有意思的动效,比如屏保,今天我们就来一步步使用贝塞尔曲线做一个屏保动效
准备工作
不管做哪种动效,一些变量比如窗口宽高,中心点坐标都是需要的,所以先把这些变量创建出来
在Canvas
里面获得了画布的宽高width
和height
,并且计算出了中心点的x坐标与y坐标centerX
与centerY
,接下去就要开始绘制贝塞尔曲线了
绘制曲线
我们都知道绘制贝塞尔曲线其实最关键的部分就是确定那几个控制点,而三阶曲线一共需要四个点,第一个点毫无疑问就确定为画布中心点了,其余三个点我们就把他们放置在一个椭圆上,为什么不是在一个圆周上而是椭圆呢,因为如果将三个点放在一个圆周上的话,我们只能改变圆周的半径,达到的效果也只是动效的范围变大变小,但是椭圆就不一样了,椭圆里面有长轴和短轴,可以通过不断改变长短轴的长度来改变椭圆的形状,从而最终出现的效果也是不一样的,好了,首先得知道如何计算椭圆上每一个点的坐标
上面就是计算椭圆上某一个点的xy坐标,其中xRadius表示x轴上轴长,yRadius表示y轴上的轴长,将上面这俩公式转换成代码就是下面这样
从这两个函数里面知道如果想要在椭圆上获得某个点的坐标,需要知道长短轴大小,中心点坐标以及当前点所对应的角度,我们除了中心点坐标是已知的,其他两个现在还都未知,那么先定义两个变量作为长短轴大小
maxLength
就是长轴大小,minLength
就是短轴大小,而角度的话,由于我们这里是要画180根曲线,所以我们可以把椭圆分成180份,每两度一个点
这样就能先把第一组控制点的坐标创建出来
第二组第三组控制点坐标在第一组的基础上做点变化,第二组的角度都增加30度,第三组的角度都增加60度,代码如下
现在绘制贝塞尔曲线所需要的控制点都有了,接下来就是把每条曲线对应的Path
做出来
接下来的事情就很简单了,在Canvas
里面把这180根贝塞尔曲线绘制出来,看代码
这里还给曲线增加了点pathEffect
,算是点缀,可加可不加,运行一遍代码后就得到下面这样的图案
好家伙整了个轮回眼出来了,当然咱今天不是来画轮回眼的,继续来做我们的动效,开头说了咱用椭圆主要是因为椭圆的长短轴可以来回变化,从而形成的样子也不一样,那么这里也给长短轴增加点变化
这里先做了两个循环变化的动画变量,baseX
表示x轴上的轴长变化,初始是从长轴变化到短轴,而baseY
则反过来,它代表Y轴上的轴长变化,初始是从短轴变化到长轴,将这两个动画变量替代原先三组控制点里面的轴长
现在得到的效果就是下面这样的
除了轴长,我们给角度也加上一个动画变量,动画变量代码如下
三组控制点的代码更改为
可以看到在不同的坐标里面,角度angleDiff
都会乘上或除上一个数字,数字具体是啥没有具体要求,主打一个随机,目的就是让不同的坐标角度变化速率不一样,现在我们的动效就变成下面这样的了
那既然角度后面的数据是随机的,那么换一组数字是不是可以得到其他效果呢,我们来试一下
这里又做了三组控制点,在角度变化上跟上面的做了区分,然后我们使用这三组新的控制点来看看可以做出怎样的效果出来
效果就变成另外一种样式了,刚才我们依靠着改变角度的变化速率实现了两种不同的动效,现在将这两种动效合并,怎么合并呢?在pathList
里面根据下标判断,如果是偶数就用第一种,如果是奇数就用第二种,代码如下
这样子做就能把两种效果合并在一起了,得到的效果就是下面这样
大致的一个样子就画好了,现在来优化一下整个视觉体验
添加颜色切换
现在我们的效果还只是纯白色,太单调了,准备给它多加点颜色上的变化才会好看些,这样的话我们先创建个颜色数组,里面放上需要显示的颜色色值
总共有这么几个颜色,然后通过访问colorList
的下标值来给动效加颜色,而这个下标值就用循环动画来创建,这样动效显示的颜色就可以循环从colorList
中获取,实现的代码如下
这里在获取到下标值的时候,还使用了animateColorAsState
函数让颜色之间的切换有个动画过渡的过程,而给动效染色就使用lineColor
变量
还添加了点颜色上的渐变,让效果更加立体些
改变轴长
发现整体效果上在某些时候周围留白的空间比较大,造成这种现象的原因是因为短轴与长轴相差过大,所以我们将短轴与长轴的值稍微调整一下,让它们之间的差值不要过大
改完轴长后的效果如下
改变dash间隔
现在dash的间隔还只是个写死的值,这边希望让这个值也有个区间的变化,所以我们也创建个dash的循环改变的变量,并且把这个变量代入到绘制曲线的代码中
得到的效果如下
画布旋转,添加模糊效果
最后一步我们让画布旋转起来,并添加模糊效果,用到的操作符分别是rotate
和blur
,rotate
传入的值可以用我们前面已经创建的angleDiff
,也可以在新建一个角度变化的动画变量,这里就新建一个,blur
就传入5.dp
,带点小模糊,代码如下
效果就变成下面这样
最后如果想要弄成屏保的话,只需要将窗口改成全屏,宽高设置为屏幕宽高即可,代码如下
这里就不放效果图了,主要是太大了。
总结
这个动效其实可以做成很多种样子,代码中很多地方改一些参数,样式形状都变了,有兴趣的可以自己去动手尝试下。