终于可以写点Compose了,这次来做个吹泡泡效果

3,620 阅读8分钟

前言

又是两个半月,翻了翻上一次写Compose动效果已经是两月份的事情了,比起去年来讲今年的Compose动效更新的实在是不勤快,不是不想写,实在是活太多,分身乏术,没办法,赚钱第一,毕竟还要养家糊口呢,然后随着上周把几个需求带上线后(连上六天班,居然发了三个小版本),终于有那么几天的休息时间,不用在盯着VsCode敲ts,终于可以打开IDEA敲点kt了

写点啥

前段时间陪女儿去了海洋公园,看见了一些小孩拿着个泡泡机在biubiubiu的放"泡",盯着那些泡泡看了会,职业病又犯了,感觉自己可以尝试着实现一个吹泡泡的效果,刚好也要儿童节了,写点小孩子喜欢的东西,那么让我们开始吧

画一个泡泡

第一步我们先画一个泡泡,泡泡是个圆,所以百分百的得围绕着drawCircle开始画,在画布上随意画个圆,定好圆心,颜色,半径等属性,一个简单的圆就出来了

001.png 002.png

然后我们要让这个圆变的透明,然后看起来立体一些,怎么做呢?可以使用Color.Transparent和白色形成一个雷达渐变色

003.png

敲完这些代码后就得到了这么一个圆

004.png

是透明了,但透明的不多,跟裹了层雾霾一样,咱吹出来的泡泡要是这样子的话那肯定飞不起来,所以得加大透明的范围,怎么加大呢?再多加几个Color.Transparent

005.png 006.png

现在我们这个圆变的透明带渐变的了,但看起来还是不很立体,原因是像泡泡这样一个透明的圆形物体在阳光下它是会有一个反光的效果的,这个反光部分在泡泡上就会显得范围比背光的要大,所以我们应当让这边画出来的圆也有个渐变多少的区分,方式就是改变我们渐变的圆心位置,让它带点小偏移

007.png 008.png

圆心小偏移了以后的确渐变范围能区分了,但是这个范围也太大了,我们想让渐变的范围小点,可以通过增大渐变范围的半径来实现,像这样

009.png 010.png

是不是有那么点感觉了,我们再给这个圆的反光位置加点高光效果,让它更加立体一些,其实就是画个带点小角度的弧线,不细讲了,直接上代码~

011.png

上泡泡~

012.png

画多个泡泡

现在已经知道了如何绘制一个泡泡,我们就要开始本篇文章的主题,做个泡泡动效,先创建一个代表泡泡的对象,里面有这么几个属性

013.png
  • x:泡泡的中心x坐标
  • y:泡泡的中心y坐标
  • shadowOffsetx:渐变的中心点x坐标的偏移量
  • shadowOffsety:渐变的中心点y坐标的偏移量
  • color:泡泡的颜色
  • radius:泡泡的初始半径大小
  • maxRadius:泡泡的最大半径大小
  • startAngle:高光效果圆弧的起始角度

这里需要解释下为什么要设定半径初始值和最大值,玩过泡泡机或者吹过泡泡的人都知道,泡泡刚出来的时候不是最大的,得完全从泡泡机里面出来后在变成最大的,所以我们这里泡泡刚生成的时候会有个半径上增大的过程,现在我们来创建一个数组来保存所有泡泡

014.png

往这个数组里面塞泡泡的过程我们放在一个副作用里面进行,副作用里面使用一个flow,flow的上游设定制造泡泡以及渲染泡泡的时间间隔,下游用来生成泡泡,代码如下

015.png

每当泡泡数组wList里面多了一个泡泡的时候,就会触发组件重组,重组之后副作用LaunchedEffect监听到wList大小与之前不一样了,那么就会重新执行副作用里面的代码,开始生成新的泡泡,现在思考下如何为泡泡的几个属性赋值,由于泡泡的出现位置,大小,颜色,光照位置都是随机的,所以我们几个属性的取值也要随机生成

016.png
  • widthRange:泡泡中心点x坐标的取值范围
  • heightRange:泡泡中心点y坐标的取值范围
  • bubbleRadius:泡泡最大半径的取值范围
  • shadowOffset:渐变范围中心点的偏移量范围
  • startAngleRange:高光圆弧的起始角度

颜色取值的话随机找了几个颜色放在一个数组里面

017.png

这样生成泡泡的代码就可以写成下面这样

018.png

刚才说过在重组过程中泡泡还要渲染,每次渲染的时候每个泡泡都要更新自己的大小,所以先在Bubble类里面添加一个更新函数update,update里面逐步增加半径大小,直到达到最大值,并且在重续时候遍历wList,每个泡泡都要调用update函数更新自己的值

019.png 020.png

最后就是Canvas里面的绘制所有泡泡部分,单个泡泡的绘制我们在上面已经讲过了,这里需要遍历wList,将单个泡泡的绘制流程拿进来,稍微调整几个值就可以了,看代码

021.png

一个生成多个泡泡的过程就做好了,效果是这样的

022.gif

目前做出来的泡泡都是到了最大半径值以后就不动了,而实际情况应该是泡泡到了最大之后过段时间就碎掉了,所以Bubble类里面在新增两个属性,一个是life泡泡的生命值,泡泡半径到达最大值后life开始减少,减少到没有生命值的时候,泡泡就不会被绘制出来,所以另一个属性是delete,当为true的时候,泡泡就不会被绘制,对应的代码如下

023.png 024.png

现在泡泡就不会一直扎堆生成了,每个泡泡都只会出来一会,然后就消失了,看下效果

025.gif

让泡泡飞一会

到了最后一步了,泡泡有了就该飞,怎么飞呢?那肯定也是通过改变泡泡的xy坐标来实现,先尝试下在update里面随便给xy更新个值看看

026.png 027.gif

我们看到虽然泡泡们是动了,但是方向都是朝着右下方移动的,那是因为我们xy都是在不断增加2个单位的距离,而真实场景中,泡泡都是由一个位置朝外围扩散的,所以我们的x坐标变化值应该是有正有负,而y坐标的变化值应该是负数,也就是从当前位置向上移动,那么这里给Bubble增加一个属性xDis表示x坐标的变化量,这个变化量取值范围也是由一个负数到一个正数之间

028.png

然后在update函数里面,x自然是每次更新xDis的大小,y的话每次更新的值这里打算使用对数函数来计算,为什么使用对数函数呢,先看下面的代码

029.png

这里对1到8这八个整数进行了对数计算,我们看到计算得到的结果中,前面的结果之间差距还在0.3左右,到了后面,差距就缩小为0.13左右了,相当于就是一个减速的过程,所以如果把ln函数里面参数换成x坐标的话,那么y坐标的更新也是个减速的过程,比较贴近泡泡产生后由于空气阻力速度减缓的一个效果,update函数更新后如下所示

030.png

现在的泡泡就可以实现全都朝外扩散,并向上移动的效果了,一起看下

031.gif

接下来我们再来将泡泡扩散的起始位置固定在某一个小范围里面,而不是整个窗口宽度,毕竟泡泡都是从泡泡机的一个口里面出来的,缩小这个范围就很简单,把上面的widthRange的范围缩小一点就好了

032.png

最后我们给背景加一张图片,看起来像是在现场吹泡泡一样

033.png

来看下最终我们吹出来的泡泡啥样

034.gif

总结

这个动效相对来讲不是很难,但也能找出来几个知识点

  • 实现立体效果:可以使用雷达渐变,渐变数组中透明色可以多一些
  • 光照背光效果:可以将雷达渐变圆心的坐标加点偏移量
  • 实现减速效果:可以使用对数函数来计算坐标

这篇文章就写到这了,喜欢的话可以扣一下小爱心,不喜欢的可以扣一下左上角小箭头,下次见~拜拜~