暗いので電気をつけて続きを読みましょう

フロントエンドでは、2 つのコントロール間の距離は何ピクセルか、テキストとコンテナーの余白の間の距離は何ピクセルかなど、UI デザイナーとやり取りするときにピクセルという言葉がよく使われることがあります。ここでのピクセルは通常ピクセルは測定単位として存在しますが、小さなコントロールとしてピクセルを使用しようとしたことはありますか? 各ピクセルを大きくしたり小さくしたり、色を暗くしたり明るくしたりするため、今日の記事では、Compose DeskTop でピクセルを再生する別の方法を引き続き紹介します。

ピクセルを描画する

まず、Canvas上記のすべてのピクセルを描画します。ピクセルを描画するために必要な変数は次のとおりです。

画像.png
  • screenW: キャンバス幅、キャンバス内のサイズによってリアルタイムで更新されます
  • screenY: キャンバスの高さ、キャンバスのサイズによってリアルタイムで更新されます
  • gridCount: 幅または高さで区切る必要があるピクセル数
  • xUnit: 単一ピクセルの幅
  • yUnit: 単一ピクセルの高さ
  • pRadius: 描画する必要がある小さなドットの半径
  • xList: 描画されたすべての小さなドットの x 座標
  • yList: 描画されたすべての小さなドットの y 座標

次に、Canvas内部の 2 つのコレクションを走査しxListyListすべての小さな点を描画します。描画方法は誰でもよく知っています。drawCircle関数を使用します。

画像.png

密かに恐怖するメリット〜

画像.png

小さな黒い点の束を取得しました。次に、いくつかの小さな黒い点の透明度の値を変更してみます。たとえば、特定の位置をクリックした瞬間から、この位置の透明度の値が最小になり、その後、透明度の値が外側に向かって1つずつ大きくなっていき、透明度の値が1になるまでのコードは以下のようになります

画像.png

ここでは、クリックされた位置を保存するために使用される 2 つの新しい変数tapXとx 座標と y 座標を示します。ループ トラバーサル コードでは、透明度の値を示すために2 つの新しい変数tapYが追加され、透明度の値はクリックされた位置から外側に向かって 1 つずつ増加します。画面をクリックすると、1 未満の点を同時に描画する場合に透明値が設定されそれ以外の場合は透明値が設定されません。以下はレンダリングですxdisydisxdisydisalpha

0613aa1.gif

クリックした位置から外側に向かってドットの透明度が大きくなっているので、同じロジックでドットの半径を外側に向かって1つずつ大きくしていきます

画像.png

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

0613aa2.gif

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

画像.png

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

画像.png

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

画像.png

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

画像.png

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

画像.png 0614aa1.gif

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

关灯后的效果

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

画像.png

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

画像.png 0614aa3.gif

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

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

画像.png

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

画像.png

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

画像.png

调节电灯亮度

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

画像.png

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

画像.png

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

画像.png

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

画像.png 0614aa4.gif

调节灯光扩散区域大小

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

画像.png

次に、拡散領域の描画条件を変更します。以前はdiv拡散領域の描画条件として1未満でしたが、光の照射範囲がウィンドウ全範囲である必要があるため、この制限を追加する必要はありません。他の場所circleSizeでも最小値より大きい場合などの描画条件があるので最終的なコードは以下のようになります

画像.png

なぜスイッチがオンかオフかを判定する条件を設けていないのかというと、スイッチをオフにするとウィンドウが突然真っ暗になってしまうためで、その際のトランジション効果も期待したいのです。現在のエフェクトを見てみましょう

0614aa5.gif

ライトのオンとオフのエフェクトが完成しました。あとは、本を読んでいる画像を見つけて、Imageそれを最外層のコンポーネントで表示すれば、ライトをオンにして本を読むエフェクトが完成します。

画像.png 0614aa6.gif

送信元アドレス

要約する

最近、面白いアニメーション効果を作る方法を考えています。Android View よりも Compose でアニメーション効果を作成する方がはるかに簡単だと感じています。たとえば、この記事で言及されている内容を変更する必要があります。エフェクトが出るので再度変更するとデータロード後のトランジションエフェクトも出てきますので自分のプロジェクトで試すこともできます

おすすめ

転載: juejin.im/post/7244526264617664572