用Compose又做了三个挺吼看的loading动效

3,117 阅读10分钟

最近又新做了三个Loading,不多,但都是自己原创的,代码已经上传了,有兴趣的小伙伴可以clone下来看看,下面就介绍下这三个Loading的制作过程,同样的,大家可以选择感兴趣的loading来看。

源码地址

万花筒loading

这个loading看起来花里胡哨的,其实做起来还是蛮容易的,主要是用到了BlendMode这个参数,老规矩,我们绘制动画第一步,首先将需要的变量创建好

image.png

画布的宽width,画布的高height,以及圆周运动必需品中心点坐标centerXcenterY,接着来做几个绕着中心点转圈的圆,我们知道画圆主要的就是确定好它的center的位置,center就是个Offset,所以这里创建个数组用来存放这些圆的Offset

image.png

offsetList就是用来存放Offset的数组,pointXpointY是通过半径,中心点,角度来计算目标点坐标的函数,不多做介绍了,源码里面有,这里可以看到总共有十个Offset,对应了十个圆,每个圆的圆心距离中心点坐标60f,圆与圆之间的角度偏移量是36f,刚好平分整个圆周空间,我们接下来遍历offsetList来将十个圆画出来

image.png

我们看到圆的半径居然也要50f,那画出来的效果不就十个圆基本挤在一起了吗,我们看下效果

image.png

根本就看不出来圆嘛,其实这个才是我们想要实现效果的第一步,先将圆都重叠在一起,接下来就是主角BlendMode登场了,可能有些小伙伴对这个还比较陌生,没见过啊,其实它在我们使用DrawScope里面的api的时候就已经出现过了,基本每一个drawXXX的函数的参数列表里面,最后一个参数就有它的身影,比如在这里要使用的drawCircle函数里面

image.png

我们看注释里面的Blendmode的描述就是Blending algorithm,一种混合算法,也就是在绘制时候将绘制的图形像素与Canvas上对应位置的像素进行混合形成新的像素,类似于传统Android里面的PorterDuff,基本PorterDuff里面的模式Blendmode都有,同时Blendmode还有一些自己的模式,其中引起我注意的就是Plus模式

image.png

我们可以看到注释里面对这个模式的描述是重叠部分的像素的透明度会降低,也就看起来像是该部分的颜色变深了一样,那么对于我们demo中十个圆刚好就是处于重叠状态,我们使用这个模式会出现什么现象呢,来试试看

image.png image.png

怎么感觉没啥变化?其实是有变化的,Plus模式的注释可能看起来比较难以理解,其实最好理解的方式就是从这个模式命名本身出发,Plus模式意思是加模式,就是将两个重叠涂层的十六进制色值加一起,而我们这里用的是Color.Red,色值为0xFFFF0000,排除前面的透明值通道,这里就是首先对两个FF0000进行十六进制的加法,算出来的结果如下所示

image.png

得到的是FE0000,可不就还是红色嘛,虽然色值不同,但是用肉眼自然没法区分开来,我们再看看将FE0000FF0000相加得到的是什么

image.png

FD0000,色值不同但依然还是红色,所以这里的例子我们不能用Color.Red,换个色值试试,比如FF1D1D这个色值,再看看效果如何

image.png image.png

我们看到重叠部分的色值已经发生了变化了,多次重叠以后,整体就看起来像一朵红花一样,那么我们已经给十个重叠的圆加好了混合模式,因为做的是万花筒效果,所以颜色得多一些,这里再多加几个颜色,并且定时切换

image.png

比如这里有六种颜色,接着使用循环动画不断取这个colorList的下标值,然后通过animateColorAsState函数切换下标值对应的颜色,代码如下

image.png image.png

color作为绘制十个圆的色值以后,效果就出来了

image.png 0721aa1.gif

效果如何?我们接着再给这十个圆加点动效,比如绕着中心转动,并且十个圆与圆心距离有个渐近渐远的过程,那么再新建两个循环动画

image.png

然后再将diffAnglediffDis这俩值参与到计算十个圆的Offset的数组当中

image.png

我们这个万花筒的Loading效果就做出来了,最终效果图如下

0721aa2.gif

转动的蜂窝碎片

这个是从上一篇蜂窝墙那里做完以后想到的,我们绘制蜂窝墙的时候,绘制范围是铺满整个画布的,蜂窝墙整体其实就是个长方形,所以我们可以通过等分画布宽高来找出坐标点来绘制一个个蜂窝格子,但是如果是要画其中一小部分,就要用另一种方式,从中间向外画,我们来看下如何做,首先还是将一些必要的变量创建出来

image.png

基本跟上面的万花筒一样,多了一个sideWidth,表示一个六边形的边长,多了三个list,xListyList是用来存放所有需要绘制的六边形的中心点,anglist是绘制六边形六条边的时候需要的角度,pathList是存放需要绘制六边形需要用到的Path,那么先在中心位置画一个六边形来练练手,在xListyList中分别放入中心点坐标centerXcenterY,然后通过遍历xListCanvas中将每个点对应的六条边画出来,代码如下

image.png image.png

中间这个六边形画好了,然后给这个六边形的六条边对应的方向也画上六边形,那么第一步,算出周围六边形的中心点与已经画好的六边形的中心点之间的距离,我们用勾股定理就能得出

image.png

然后是六个中心点的角度

image.png

现在就可以在xListyList中加入六个点的坐标了

image.png

由于之前就已经在Canvas中加入了遍历xList绘制六边形的代码了,所以这里直接就能获得另外六个六边形

image.png

一个小的蜂窝碎片就做出来了,简单不,我们继续添加些坐标,把这个蜂窝碎片弄的大些

image.png image.png

接下来就是上色了,上色的第一步还是先填充满蜂窝的小格子,也就是需要绘制一些六边形样式,这里创建一个pathList来存放绘制六边形需要的Path,然后遍历xList或者yList来生成一个个PathaddpathList里面去

image.png

然后在Canvas中遍历生成的pathList,并使用drawPath函数绘制出一个个六边形

image.png image.png

效果就出来了,然后我们多创建几个颜色,并且使用animateColorAsState函数来切换

image.png

Canvas中将color作为绘制六边形的颜色值,我们就得到了一个颜色可变的蜂窝碎片

image.png 0724AA1.gif

还剩下最后一步让这个碎片转动起来,也就是让我们的Canvas转动起来,如何转动呢?就需要用到Modifier的一个操作符graphicsLayer,它里面有控制x,y,z轴转动的参数,分别是rotationXrotationYrotationZ,比如我们想要让它绕着x轴转圈,那么就需要有个0到360度变化的动画过程

image.png

然后将canvasAngle赋值给graphicsLayerrotationX参数,我们的碎片就转起来了

image.png 0724aa2.gif

我们还可以把canvasAngle作用在roatationYrotationZ上面,让它再其他方向也有转动的效果,不过这里打算再新建两个转动的变量,目的是让这三个方向转动的角度速率都不一样,代码如下

image.png 0724aa3.gif

转动的几何图形

说实话这个能不能叫Loading我也不知道,只是忽然有个想法想试试看,之前画过几个贝塞尔曲线,但都是偏向简单的,一根两个组合在一起使用的那种,那么如果是许多根贝塞尔曲线在一起,会有什么效果呢,所以就试了一下,一些准备工作就简单带过了,直接上代码

image.png

我们知道画贝塞尔曲线需要几个控制点,三个控制点构成一个二阶曲线,四个控制点构成一个三阶曲线以此类推,我们这里按照控制点顺序分别命名为P0,P1,P2....那么如果在一个圆周上,有count个点作为P0点,在另外一个圆周上也有count个点作为P1,然后同样在另外一个圆周上有count个P2的点,最后将每个圆周上对应下标值的点组合成一个二阶曲线,我们看看会出现个怎样的图形

image.png

count是需要绘制的曲线个数,unitAngle是圆周上的点间隔的单位角度,baseRadius是P0点的圆周的半径,后面的圆周的半径都是在baseRadius上做增加或减少,然后新建了六个list,分别存放P0,P1,P2的xy坐标,我们可以看到计算P1,P2点的坐标的半径与角度都与P0有一些区别,然后新建一个pathList用来存放二阶曲线的Path,然后在Canvas中遍历这个pathList将所有Path绘制出来

image.png

这里在绘制的时候还加上了混合模式,目的是让重叠的地方颜色可以变换一下,达到整体立体的感觉,效果就是下面这样

image.png

这是我们画二阶曲线的效果,这里再增加一组控制点,将二阶变成三阶再看看效果

image.png image.png

跟上面的效果比起来又有点膨胀的感觉,这里我们发现了,每一组控制点在计算的时候,角度那一部分该变量都是一个定值,比如it * unitAngle+80f, 那么如果我们将这个定值变成一个可变值,会有什么效果呢?

image.png

比如这里有一个60度到300度的一个变化动画,我们将angleDiff代入到计算控制点的代码中

image.png

这里给除P0外的控制点,在计算x或者y坐标中,横坐标对angleDiff做了除法,分母是控制点下标值加一,纵坐标对angleDiff做了乘法,乘上的也是控制点下标值加一,这些值都是自定义的,大家可以按照自己喜好来定,现在运行一遍看看效果图

0725aa1.gif

我们就得到了一个会转动的立体图形,这里并没有像上面那个蜂窝碎片一样调用rotationX或者rotationY来实现立体转动效果,而是让若干条贝塞尔曲线不断更改绘制角度从而来实现这样的一种视觉效果,这样的思路可能会对以后做其他效果会产生一些帮助,言归正传,现在画出来的是三阶曲线,那能不能在多画几阶呢,想看看多阶曲线能产生什么样的效果,可以的,很容易,再调用一次cubicTo函数就好了,那么我们需要再多创建三组控制点

image.png

然后将这三组新的控制点代入到另一个cubicTo函数

image.png 0725aa2.gif

就这样做出来了一点科技感的味道在里面,最后再稍微给这个效果美化一下,加点渐变色,另外给Path加点dashPathEffect的效果

image.png 0725aa3.gif

最终一个好看但不实用的loading就做好了~

总结

这次做的三个loading效果虽说实用性不大,但是还是用到了一些绘图的小技巧,比如混合模式之类的,可能会在今后的开发中对自己有所帮助。