注册

天黑了,开个灯继续看书

像素点这个词对于前端来讲可能与UI设计师们打交道的时候用的会比较多一些,比如两个控件之间距离多少个像素,这个文字离容器边距多少个像素,这里的像素通常是以一种度量单位而存在,那大家有没有试过将像素点作为一个个小的控件来使用呢?让每个像素点可以变大变小,颜色可以变深变浅,那么今天这个文章我们继续在Compose DeskTop上来带大家看看像素点的另一种玩法。


画出像素点


首先我们在Canvas上画出所有像素点,下面是画像素点所需要的变量


image.png

  • screenW:画布宽度,在Canvas中通过Size实时更新
  • screenY:画布高度,在Canvas中通过Size实时更新
  • gridCount:宽度或者高度上需要分出的像素数量
  • xUnit:单个像素的宽度
  • yUnit:单个像素的高度
  • pRadius:需要绘制的小圆点半径
  • xList:所有绘制出来的小圆点的x坐标
  • yList:所有绘制出来的小圆点的y坐标

然后在Canvas里面遍历xListyList这两个集合,将所有小圆点都画出来,怎么画的大家都很熟悉了,使用drawCircle函数


image.png

前方密恐福利~


image.png

我们已经获得了一堆小黑点,现在我们来尝试下更改一些小黑点的透明值,比如从我点击某一个位置开始,该位置的透明值最小,然后逐个向外透明值变大,直到透明值变成1为止,代码如下


image.png

这里新增两个变量tapXtapY用来保存点击位置的x坐标与y坐标,在循环遍历的代码里面,新增了xdisydis两个变量表示透明值,并且从点击位置开始向外递增透明值逐个变大,到第十个黑点的时候透明值就变成1了,当屏幕点击以后,xdisydis同时都小于1的点在绘制的时候都设置透明值alpha,否则就不设置透明值,下面是效果图


0613aa1.gif

圆点的透明值已经从点击位置开始向外变大了,我们再用同样的逻辑,让圆点的半径逐个向外变大


image.png

这里就做了一个小改动,将半径去乘上刚才算出来的透明值,让那些变透明的圆点同时也能有一个大小上的变化,我们再看下效果图


0613aa2.gif

可以看到我们的小圆点已经呈现出向外扩散,并且在色值与大小上都有了一定的变化,但是如果说扩散的话这里还看着有点别扭,因为一般的扩散都是以一个圆形的形状扩散的,而这里是正方形,所以我们得想办法把这个正方形也弄成圆形,怎么弄呢?那就要改变一下计算透明值与半径大小的方式了,之前是按照向外扩散经过的圆点个数来逐渐改变圆点的透明值与半径大小的,关键代码是这俩句


image.png

那么这种计算方式肯定是斜着的方向扩散的距离要大一些,所以我们不能再限制个数了,而是限制一下扩散的距离,也就是将这个扩散的圆的半径得先确定好,比如变量circleSize就是这个扩散的半径


image.png

然后我们需要做的就是计算出两点之间的距离除上这个circleSize,得到的值如果小于1那么就是我们需要的透明值,大于等于1我们就正常处理,这里唯一需要琢磨的就是如何计算两点之间的距离,四个字,勾股定理


image.png

最后一步开根号kotlin里面有现成的函数sqrt,那么计算两个小圆点之间的距离以及透明值的代码如下所示


image.png

接下去只需要将画圆点的透明值设置成div以及半径去乘上div就好了


image.png
0614aa1.gif

我们看到效果图上扩散的区域已经变成了一个圆形了,到了这里我们像素点的主要玩法就讲完了,接下去就是利用上面讲到的知识点,来做一个开灯关灯的效果


关灯后的效果


关灯后一般都是漆黑一片,但隐约还能有点能见度,所以我们这里的黑也要带点透明度,然后圆点的个数也要增多,要让单个圆点变得不明显,所以gridCount首先增加到300


image.png

然后将非扩散区域的背景色调成有点透明的黑色,并且增大圆点半径值,目的是去除圆点之间的间隙,扩散的圆点的背景色也设置成带点透明,并且半径在乘上div的基础上再减小一点,目的是加强扩散区域的灯光朦胧感


image.png
0614aa3.gif

绘制电灯,确定扩散中心位置


到了这里,扩散区域的代码暂时先告一段落,我们将电灯绘制出来,后面电灯的灯泡就作为我们扩散的中心区域,绘制电灯都是些基本Canvas绘图技巧,不多做介绍,直接贴上电灯的代码


image.png

drawCircle函数用来画灯泡,灯泡的中心点就是我们扩散的中心坐标tapX,tapY,函数drawline是画的电线,函数drawArc是画的罩在灯泡外面的灯罩,另外tapX,tapY的具体值就从点击获取变成了一个固定值


image.png

整个电灯的代码就完成了,效果如下


image.png

调节电灯亮度


当我们在生活中调节灯泡亮度的时候,灯泡的亮度会越来越亮,颜色会越来越深,那么这边如果要实现这一点的话,就需要确定一个最亮值以及最暗值,然后通过函数animateColorAsState来创建个颜色过渡的动画过程


image.png

lightState是这个开关灯的状态,作为当前所在的函数的入参从上层传进来


image.png

我们在最外层Window函数里面建立个菜单项,添加两个选项开灯与关灯,用来控制lightState的值


image.png

有了切换状态的开关,就开启了颜色过渡的动画,灯泡的色值就用lightColor来取代


image.png
0614aa4.gif

调节灯光扩散区域大小


灯光亮度能够有个由弱到强的过程了,那么灯光的扩散范围也应该有所变化,而上面我们已经知道了,控制扩散区域大小的变量就是circleSize,所以我们只要通过改变circleSize就能达到改变扩散范围的目的了,这里同样也创建个circleSize的过渡动画


image.png

然后我们更改下绘制扩散区域的条件,之前是将div小于1作为绘制扩散区域条件,现在就不需要加这个限制了,因为灯光照射的范围肯定是整个窗口范围,所以最后扩散的区域一定是到窗口以外的地方,但是绘制的条件还是有的,那就是circleSize大于最小值的时候,所以最终的代码如下


image.png

至于为什么不将判断条件设置成判断开关的开启状态是因为当开关关闭的时候,窗口一下子就变黑了,这里也希望关闭时候也有一个过渡的效果,我们看下现在的效果


0614aa5.gif

开关灯的效果就做好了,现在我们可以找一张看书的图片,然后在最外层用Image组件展示出来,那么开灯看书的效果就做好了


image.png
0614aa6.gif

源码地址


总结


最近在各种琢磨怎么做点好玩的动画效果出来,感觉在Compose里面做动效比在Android View里面简单多了,比如像这篇文章里面说到的内容,是不是改一改,一个水波纹效果就出来了,再改一改,一个数据加载完以后的转场效果也出来了,大家也可以在自己项目里面动手试试看


作者:Coffeeee
链接:https://juejin.cn/post/7244526264617664572
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册