欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android實現(xiàn)點匯聚成字的動態(tài)效果詳解

 更新時間:2022年07月15日 08:36:30   作者:島上碼農(nóng)  
在引入?fl_chart?繪制圖表的時候,看到插件有下面這樣的動效,隨機散亂的圓點最后組合成了?Flutter?的?Logo,挺酷炫的。本篇我們來探討類似的效果怎么實現(xiàn)

前言

在引入 fl_chart 繪制圖表的時候,看到插件有下面這樣的動效,隨機散亂的圓點最后組合成了 Flutter 的 Logo,挺酷炫的。本篇我們來探討類似的效果怎么實現(xiàn)。

點陣

在講解代碼實現(xiàn)之前,我們先科普一個知識,即點陣。點陣在日常生活中很常見,比如廣告屏,停車系統(tǒng)的顯示,行業(yè)內(nèi)稱之為 LED 顯示屏。

LED 顯示屏實際上就是由很多 LED 燈組合成的一個顯示面板,然后通過顯示驅(qū)動某些燈亮,某些燈滅就可以實現(xiàn)文字、圖形的顯示。LED 顯示屏的點距足夠小時,色彩足夠豐富時其實就形成了我們?nèi)粘5娘@示屏,比如 OLED 顯示屏其實原理也是類似的。之前報道過的大學(xué)宿舍樓通過控制每個房間的燈亮燈滅來形成文字的原理也是一樣的。

現(xiàn)在來看看 LED顯示文字是怎么回事,比如我們要 顯示島上碼農(nóng)的“島”字,在16x16的點陣上,通過排布得到的就是下面的結(jié)果(不同字體的排布會有些差別)。

因為每一行是16個點,我們可以對應(yīng)為16位二進制數(shù),把黑色的標(biāo)記為1,灰色的標(biāo)記為0,每一行就可以得到一個二進制數(shù)。比如上面的第一行第8列為1,其他都是0,對應(yīng)的二進制數(shù)就是0000000100000000,對應(yīng)的16進制數(shù)就是0x0100。把其他行也按這種方式計算出來,最終得到的“島”字對應(yīng)的是16個16進制數(shù),如下所示。

 [
   0x0100, 0x0200, 0x1FF0, 0x1010, 
   0x1210, 0x1150, 0x1020, 0x1000,
   0x1FFC, 0x0204, 0x2224, 0x2224,
   0x3FE4, 0x0004, 0x0028, 0x0010
 ];

又了這個基礎(chǔ),我們就可以用 Flutter 繪制點陣圖形。

點陣圖形繪制

首先我們繪制一個“LED 面板”,也就是繪制一個有若干個點構(gòu)成的矩陣,這個比較簡單,保持相同的間距,逐行繪制相同的圓即可,比如我們繪制一個16x16的點陣,實現(xiàn)代碼如下所示。

var paint = Paint()..color = Colors.grey;
final dotCount = 16;
final fontSize = 100.0;
var radius = fontSize / dotCount;
var startPos =
    Offset(size.width / 2 - fontSize, size.height / 2 - 2 * fontSize);
for (int i = 0; i < dotCount; ++i) {
  var position = startPos + Offset(0.0, radius * i * 2);
  for (int j = 0; j < dotCount; ++j) {
    var dotPosition = startPos + Offset(radius * 2 * j, position.dy);
    canvas.drawCircle(dotPosition, radius, paint);
  }
}

繪制出來的效果如下:

接下來是點亮對應(yīng)的位置來繪制文字了。上面我們講過了,每一行是一個16進制數(shù),那么我們只需要判斷每一行的16進制數(shù)的第幾個 bit是1就可以了,如果是1就點亮,否則不點亮。點亮的效果用不同的顏色就可以了。 怎么判斷16進制數(shù)的第幾個 bit 是不是1呢,這個就要用到位運算技巧了。實際上,我們可以用一個第 N 個 bit 是1,其他 bit 都是0的數(shù)與要判斷的數(shù)進行“位與”運算,如果結(jié)果不為0,說明要判斷的數(shù)的第 N 個 bit 是1,否則就是0。聽著有點繞,看個例子,我們以0x0100為例,按從第0位到第15位逐個判斷第0位和第15位是不是1,代碼如下:

for (i = 0 ; i < 16; ++i) {
  if ((0x0100 & (1 << i)) > 0) {
    // 第 i 位為1
  }
}

這里有兩個位操作,1 << i是將1左移 i 位,為什么是這樣呢,因為這樣可以構(gòu)成0x0001,0x0002,0x0004,...,0x8000等數(shù)字,這些數(shù)字依次從第0位,第1位,第2位,...,第15位為1,其他位都是0。然后我們用這樣的數(shù)與另外一個數(shù)做位與運算時,就可以依次判斷這個數(shù)的第0位,第1位,第2位,...,第15位是否為1了,下面是一個計算示例,第11位為1,其他位都是0,從而可以 判斷另一個數(shù)的第11位是不是0。

通過這樣的邏輯我們就可以判斷一行的 LED 中第幾列應(yīng)該點亮,然后實現(xiàn)文字的“顯示”了,實現(xiàn)代碼如下。wordHex是對應(yīng)字的16個16進制數(shù)的數(shù)組。dotCount的值是16,用于控制繪制16x16大小的點陣。每隔一行我們向下移動一段直徑距離,每隔一列,我們向右移動一段直徑距離。然后如果當(dāng)前繪制位置的數(shù)值對應(yīng)的 bit位為1,就用藍色繪制,否則就用灰色繪制。這里說一下為什么左移的時候要用dotCount - j - 1,這是因為繪制是從左到右的,而16進制數(shù)的左邊是高位,而數(shù)字j是從小到大遞增的,因此要通過這種方式保證判斷的順序是從高位(第15位)到低位(第0位),和繪制的順序保持一致。

 for (int i = 0; i < dotCount; ++i) {
  var position = startPos + Offset(0.0, radius * i * 2);
  for (int j = 0; j < dotCount; ++j) {
    var dotPosition = startPos + Offset(radius * 2 * j, position.dy);

    if ((wordHex[i] & ((1 << dotCount - j - 1))) != 0) {
      paint.color = Colors.blue[600]!;
      canvas.drawCircle(dotPosition, radius, paint);
    } else {
      paint.color = Colors.grey;
      canvas.drawCircle(dotPosition, radius, paint);
    }
  }
}

繪制的結(jié)果如下所示。

由點聚集成字的動畫實現(xiàn)

接下來我們來考慮如何實現(xiàn)開篇說的類似的動畫效果。實際上方法也很簡單,就是先按照文字應(yīng)該“點亮”的 LED 的數(shù)量,先在隨機的位置繪制這么多數(shù)量的 LED,然后通過動畫控制這些 LED 移動到目標(biāo)位置——也就是文字本該繪制的位置。這個移動的計算公式如下,其中 t 是動畫值,取值范圍為0-1.

需要注意的是,隨機點不能在繪圖過程生成,那樣會導(dǎo)致每次繪制產(chǎn)生新的隨機位置,也就是初始位置會變化,導(dǎo)致上面的公式實際不成立,就達不到預(yù)期的效果。另外,也不能在 build 方法中生成,因為每次刷新 build 方法就會被調(diào)用,同樣會導(dǎo)致初始位置發(fā)生變化。所以,生成隨機位置應(yīng)該在 initState方法完成。但是又遇到一個新問題,那就是 initState方法里沒有 context,拿不到屏幕寬高,所以不能直接生成位置,我們只需要生成一個0-1的隨機系數(shù)就可以了,然后在繪制的時候在乘以屏幕寬高就得到實際的初始位置了。初始位置系數(shù)生成代碼如下:

@override
  void initState() {
  super.initState();
  var wordBitCount = 0;
  for (var hex in dao) {
    wordBitCount += _countBitOne(hex);
  }
  startPositions = List.generate(wordBitCount, (index) {
    return Offset(
      Random().nextDouble(),
      Random().nextDouble(),
    );
  });
  ...
}

wordBitCount是計算一個字中有多少 bit 是1的,以便知道要繪制的 “LED” 數(shù)量。接下來是繪制代碼了,我們這次對于不亮的直接不繪制,然后要點亮的位置通過上面的位置計算公式計算,這樣保證了一開始繪制的是隨機位置,隨著動畫的過程,逐步移動到目標(biāo)位置,最終匯聚成一個字,就實現(xiàn)了預(yù)期的動畫效果,代碼如下。

void paint(Canvas canvas, Size size) {
  final dotCount = 16;
  final fontSize = 100.0;
  var radius = fontSize / dotCount;
  var startPos =
      Offset(size.width / 2 - fontSize, size.height / 2 - fontSize);
  var paint = Paint()..color = Colors.blue[600]!;

  var paintIndex = 0;
  for (int i = 0; i < dotCount; ++i) {
    var position = startPos + Offset(0.0, radius * i * 2);
    for (int j = 0; j < dotCount; ++j) {
      // 判斷第 i 行第幾位不為0,不為0則繪制,否則不繪制
      if ((wordHex[i] & ((1 << dotCount - j))) != 0) {
        var startX = startPositions[paintIndex].dx * size.width;
        var startY = startPositions[paintIndex].dy * size.height;
        var endX = startPos.dx + radius * j * 2;
        var endY = position.dy;
        var animationPos = Offset(startX + (endX - startX) * animationValue,
            startY + (endY - startY) * animationValue);
        canvas.drawCircle(animationPos, radius, paint);
        paintIndex++;
      }
    }
  }
}

來看看實現(xiàn)效果吧,是不是很酷炫?完整源碼已提交至:繪圖相關(guān)源碼,文件名為:dot_font.dart。

總結(jié)

本篇介紹了點陣的概念,以及基于點陣如何繪制文字、圖形,最后通過先繪制隨機點,再匯聚成文字的動畫效果??梢钥吹?,化整為零,再聚零為整的動畫效果還是蠻酷炫的。實際上,基于這種方式,可以構(gòu)建更多有趣的動畫效果。

以上就是Android實現(xiàn)點匯聚成字的動態(tài)效果詳解的詳細內(nèi)容,更多關(guān)于Android點匯聚成字的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Android性能之冷啟動優(yōu)化詳析

    Android性能之冷啟動優(yōu)化詳析

    這篇文章主要給大家介紹了關(guān)于Android性能之冷啟動優(yōu)化的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • Android編程之書架效果背景圖處理方法

    Android編程之書架效果背景圖處理方法

    這篇文章主要介紹了Android編程之書架效果背景圖處理方法,在前面一篇《android書架效果實現(xiàn)原理與代碼》的基礎(chǔ)上做了一定的修改,重寫GridView類處理了背景圖效果,需要的朋友可以參考下
    2015-12-12
  • 如何在Android App中集成支付寶和微信支付功能

    如何在Android App中集成支付寶和微信支付功能

    支付是各位Android開發(fā)者們在日常工作中經(jīng)常會遇到的一個需求,下面這篇文章主要給大家介紹了關(guān)于如何在Android App中集成支付寶和微信支付功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05
  • Android實現(xiàn)簡單圖庫輔助器

    Android實現(xiàn)簡單圖庫輔助器

    這篇文章主要為大家詳細介紹了Android實現(xiàn)簡單圖庫輔助器的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • Android仿支付寶上芝麻信用分雷達圖

    Android仿支付寶上芝麻信用分雷達圖

    最近支付寶剛剛升級,然后看了一眼里面的芝麻信用分雷達圖覺得很不錯,所以就自己動手實踐了下,這篇文章主要介紹了Android如何自定義控件,模仿支付寶上芝麻信用分雷達圖的效果,有需要的朋友們可以參考借鑒。
    2016-10-10
  • ExpandableListView實現(xiàn)簡單二級列表

    ExpandableListView實現(xiàn)簡單二級列表

    這篇文章主要為大家詳細介紹了ExpandableListView實現(xiàn)簡單二級列表,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • 解決Android SDK下載和更新失敗的方法詳解

    解決Android SDK下載和更新失敗的方法詳解

    本篇文章是對Android SDK下載和更新失敗的解決方法進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • Android編程實現(xiàn)手機震動功能的方法

    Android編程實現(xiàn)手機震動功能的方法

    這篇文章主要介紹了Android編程實現(xiàn)手機震動功能的方法,結(jié)合實例形式分析了Android實現(xiàn)手機震動功能的核心代碼與權(quán)限控制操作技巧,需要的朋友可以參考下
    2017-06-06
  • 一個吸頂Item的簡單實現(xiàn)方法分享

    一個吸頂Item的簡單實現(xiàn)方法分享

    這篇文章主要給大家介紹了一個吸頂Item的簡單實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • android調(diào)用C語言實現(xiàn)內(nèi)存的讀取與修改的方法示例

    android調(diào)用C語言實現(xiàn)內(nèi)存的讀取與修改的方法示例

    這篇文章主要介紹了android調(diào)用C語言實現(xiàn)內(nèi)存的讀取與修改的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03

最新評論