フロントエンドでは、2 つのコントロール間の距離は何ピクセルか、テキストとコンテナーの余白の間の距離は何ピクセルかなど、UI デザイナーとやり取りするときにピクセルという言葉がよく使われることがあります。ここでのピクセルは通常ピクセルは測定単位として存在しますが、小さなコントロールとしてピクセルを使用しようとしたことはありますか? 各ピクセルを大きくしたり小さくしたり、色を暗くしたり明るくしたりするため、今日の記事では、Compose DeskTop でピクセルを再生する別の方法を引き続き紹介します。
ピクセルを描画する
まず、Canvas
上記のすべてのピクセルを描画します。ピクセルを描画するために必要な変数は次のとおりです。
screenW
: キャンバス幅、キャンバス内のサイズによってリアルタイムで更新されますscreenY
: キャンバスの高さ、キャンバスのサイズによってリアルタイムで更新されますgridCount
: 幅または高さで区切る必要があるピクセル数xUnit
: 単一ピクセルの幅yUnit
: 単一ピクセルの高さpRadius
: 描画する必要がある小さなドットの半径xList
: 描画されたすべての小さなドットの x 座標yList
: 描画されたすべての小さなドットの y 座標
次に、Canvas
内部の 2 つのコレクションを走査しxList
、yList
すべての小さな点を描画します。描画方法は誰でもよく知っています。drawCircle
関数を使用します。
密かに恐怖するメリット〜
小さな黒い点の束を取得しました。次に、いくつかの小さな黒い点の透明度の値を変更してみます。たとえば、特定の位置をクリックした瞬間から、この位置の透明度の値が最小になり、その後、透明度の値が外側に向かって1つずつ大きくなっていき、透明度の値が1になるまでのコードは以下のようになります
ここでは、クリックされた位置を保存するために使用される 2 つの新しい変数tapX
とx 座標と y 座標を示します。ループ トラバーサル コードでは、透明度の値を示すために2 つの新しい変数tapY
が追加され、透明度の値はクリックされた位置から外側に向かって 1 つずつ増加します。画面をクリックすると、1 未満の点を同時に描画する場合に透明値が設定され、それ以外の場合は透明値が設定されません。以下はレンダリングですxdis
ydis
xdis
ydis
alpha
クリックした位置から外側に向かってドットの透明度が大きくなっているので、同じロジックでドットの半径を外側に向かって1つずつ大きくしていきます
这里就做了一个小改动,将半径去乘上刚才算出来的透明值,让那些变透明的圆点同时也能有一个大小上的变化,我们再看下效果图
可以看到我们的小圆点已经呈现出向外扩散,并且在色值与大小上都有了一定的变化,但是如果说扩散的话这里还看着有点别扭,因为一般的扩散都是以一个圆形的形状扩散的,而这里是正方形,所以我们得想办法把这个正方形也弄成圆形,怎么弄呢?那就要改变一下计算透明值与半径大小的方式了,之前是按照向外扩散经过的圆点个数来逐渐改变圆点的透明值与半径大小的,关键代码是这俩句
那么这种计算方式肯定是斜着的方向扩散的距离要大一些,所以我们不能再限制个数了,而是限制一下扩散的距离,也就是将这个扩散的圆的半径得先确定好,比如变量circleSize
就是这个扩散的半径
然后我们需要做的就是计算出两点之间的距离除上这个circleSize
,得到的值如果小于1那么就是我们需要的透明值,大于等于1我们就正常处理,这里唯一需要琢磨的就是如何计算两点之间的距离,四个字,勾股定理
最后一步开根号kotlin里面有现成的函数sqrt
,那么计算两个小圆点之间的距离以及透明值的代码如下所示
接下去只需要将画圆点的透明值设置成div
以及半径去乘上div
就好了
我们看到效果图上扩散的区域已经变成了一个圆形了,到了这里我们像素点的主要玩法就讲完了,接下去就是利用上面讲到的知识点,来做一个开灯关灯的效果
关灯后的效果
关灯后一般都是漆黑一片,但隐约还能有点能见度,所以我们这里的黑也要带点透明度,然后圆点的个数也要增多,要让单个圆点变得不明显,所以gridCount
首先增加到300
然后将非扩散区域的背景色调成有点透明的黑色,并且增大圆点半径值,目的是去除圆点之间的间隙,扩散的圆点的背景色也设置成带点透明,并且半径在乘上div
的基础上再减小一点,目的是加强扩散区域的灯光朦胧感
绘制电灯,确定扩散中心位置
到了这里,扩散区域的代码暂时先告一段落,我们将电灯绘制出来,后面电灯的灯泡就作为我们扩散的中心区域,绘制电灯都是些基本Canvas绘图技巧,不多做介绍,直接贴上电灯的代码
drawCircle
函数用来画灯泡,灯泡的中心点就是我们扩散的中心坐标tapX
,tapY
,函数drawline
是画的电线,函数drawArc
是画的罩在灯泡外面的灯罩,另外tapX
,tapY
的具体值就从点击获取变成了一个固定值
整个电灯的代码就完成了,效果如下
调节电灯亮度
当我们在生活中调节灯泡亮度的时候,灯泡的亮度会越来越亮,颜色会越来越深,那么这边如果要实现这一点的话,就需要确定一个最亮值以及最暗值,然后通过函数animateColorAsState
来创建个颜色过渡的动画过程
lightState
是这个开关灯的状态,作为当前所在的函数的入参从上层传进来
我们在最外层Window
函数里面建立个菜单项,添加两个选项开灯与关灯,用来控制lightState
的值
有了切换状态的开关,就开启了颜色过渡的动画,灯泡的色值就用lightColor
来取代
调节灯光扩散区域大小
灯光亮度能够有个由弱到强的过程了,那么灯光的扩散范围也应该有所变化,而上面我们已经知道了,控制扩散区域大小的变量就是circleSize
,所以我们只要通过改变circleSize
就能达到改变扩散范围的目的了,这里同样也创建个circleSize
的过渡动画
次に、拡散領域の描画条件を変更します。以前はdiv
拡散領域の描画条件として1未満でしたが、光の照射範囲がウィンドウ全範囲である必要があるため、この制限を追加する必要はありません。他の場所circleSize
でも最小値より大きい場合などの描画条件があるので最終的なコードは以下のようになります
なぜスイッチがオンかオフかを判定する条件を設けていないのかというと、スイッチをオフにするとウィンドウが突然真っ暗になってしまうためで、その際のトランジション効果も期待したいのです。現在のエフェクトを見てみましょう
ライトのオンとオフのエフェクトが完成しました。あとは、本を読んでいる画像を見つけて、Image
それを最外層のコンポーネントで表示すれば、ライトをオンにして本を読むエフェクトが完成します。
要約する
最近、面白いアニメーション効果を作る方法を考えています。Android View よりも Compose でアニメーション効果を作成する方がはるかに簡単だと感じています。たとえば、この記事で言及されている内容を変更する必要があります。エフェクトが出るので再度変更するとデータロード後のトランジションエフェクトも出てきますので自分のプロジェクトで試すこともできます