版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第Android實(shí)現(xiàn)點(diǎn)匯聚成字的動態(tài)效果詳解目錄前言點(diǎn)陣點(diǎn)陣圖形繪制由點(diǎn)聚集成字的動畫實(shí)現(xiàn)總結(jié)
前言
在引入fl_chart繪制圖表的時候,看到插件有下面這樣的動效,隨機(jī)散亂的圓點(diǎn)最后組合成了Flutter的Logo,挺酷炫的。本篇我們來探討類似的效果怎么實(shí)現(xiàn)。
點(diǎn)陣
在講解代碼實(shí)現(xiàn)之前,我們先科普一個知識,即點(diǎn)陣。點(diǎn)陣在日常生活中很常見,比如廣告屏,停車系統(tǒng)的顯示,行業(yè)內(nèi)稱之為LED顯示屏。
LED顯示屏實(shí)際上就是由很多LED燈組合成的一個顯示面板,然后通過顯示驅(qū)動某些燈亮,某些燈滅就可以實(shí)現(xiàn)文字、圖形的顯示。LED顯示屏的點(diǎn)距足夠小時,色彩足夠豐富時其實(shí)就形成了我們?nèi)粘5娘@示屏,比如OLED顯示屏其實(shí)原理也是類似的。之前報道過的大學(xué)宿舍樓通過控制每個房間的燈亮燈滅來形成文字的原理也是一樣的。
現(xiàn)在來看看LED顯示文字是怎么回事,比如我們要顯示島上碼農(nóng)的島字,在16x16的點(diǎn)陣上,通過排布得到的就是下面的結(jié)果(不同字體的排布會有些差別)。
因?yàn)槊恳恍惺?6個點(diǎn),我們可以對應(yīng)為16位二進(jìn)制數(shù),把黑色的標(biāo)記為1,灰色的標(biāo)記為0,每一行就可以得到一個二進(jìn)制數(shù)。比如上面的第一行第8列為1,其他都是0,對應(yīng)的二進(jìn)制數(shù)就是0000000100000000,對應(yīng)的16進(jìn)制數(shù)就是0x0100。把其他行也按這種方式計算出來,最終得到的島字對應(yīng)的是16個16進(jìn)制數(shù),如下所示。
[
0x0100,0x0200,0x1FF0,0x1010,
0x1210,0x1150,0x1020,0x1000,
0x1FFC,0x0204,0x2224,0x2224,
0x3FE4,0x0004,0x0028,0x0010
];
又了這個基礎(chǔ),我們就可以用Flutter繪制點(diǎn)陣圖形。
點(diǎn)陣圖形繪制
首先我們繪制一個LED面板,也就是繪制一個有若干個點(diǎn)構(gòu)成的矩陣,這個比較簡單,保持相同的間距,逐行繪制相同的圓即可,比如我們繪制一個16x16的點(diǎn)陣,實(shí)現(xiàn)代碼如下所示。
varpaint=Paint()..color=Colors.grey;
finaldotCount=16;
finalfontSize=100.0;
varradius=fontSize/dotCount;
varstartPos=
Offset(size.width/2-fontSize,size.height/2-2*fontSize);
for(inti=0;idotCount;++i){
varposition=startPos+Offset(0.0,radius*i*2);
for(intj=0;jdotCount;++j){
vardotPosition=startPos+Offset(radius*2*j,position.dy);
canvas.drawCircle(dotPosition,radius,paint);
}
繪制出來的效果如下:
接下來是點(diǎn)亮對應(yīng)的位置來繪制文字了。上面我們講過了,每一行是一個16進(jìn)制數(shù),那么我們只需要判斷每一行的16進(jìn)制數(shù)的第幾個bit是1就可以了,如果是1就點(diǎn)亮,否則不點(diǎn)亮。點(diǎn)亮的效果用不同的顏色就可以了。怎么判斷16進(jìn)制數(shù)的第幾個bit是不是1呢,這個就要用到位運(yùn)算技巧了。實(shí)際上,我們可以用一個第N個bit是1,其他bit都是0的數(shù)與要判斷的數(shù)進(jìn)行位與運(yùn)算,如果結(jié)果不為0,說明要判斷的數(shù)的第N個bit是1,否則就是0。聽著有點(diǎn)繞,看個例子,我們以0x0100為例,按從第0位到第15位逐個判斷第0位和第15位是不是1,代碼如下:
for(i=0;i++i){
if((0x0100(1i))0){
//第i位為1
}
這里有兩個位操作,1i是將1左移i位,為什么是這樣呢,因?yàn)檫@樣可以構(gòu)成0x0001,0x0002,0x0004,...,0x8000等數(shù)字,這些數(shù)字依次從第0位,第1位,第2位,...,第15位為1,其他位都是0。然后我們用這樣的數(shù)與另外一個數(shù)做位與運(yùn)算時,就可以依次判斷這個數(shù)的第0位,第1位,第2位,...,第15位是否為1了,下面是一個計算示例,第11位為1,其他位都是0,從而可以判斷另一個數(shù)的第11位是不是0。
通過這樣的邏輯我們就可以判斷一行的LED中第幾列應(yīng)該點(diǎn)亮,然后實(shí)現(xiàn)文字的顯示了,實(shí)現(xiàn)代碼如下。wordHex是對應(yīng)字的16個16進(jìn)制數(shù)的數(shù)組。dotCount的值是16,用于控制繪制16x16大小的點(diǎn)陣。每隔一行我們向下移動一段直徑距離,每隔一列,我們向右移動一段直徑距離。然后如果當(dāng)前繪制位置的數(shù)值對應(yīng)的bit位為1,就用藍(lán)色繪制,否則就用灰色繪制。這里說一下為什么左移的時候要用dotCount-j-1,這是因?yàn)槔L制是從左到右的,而16進(jìn)制數(shù)的左邊是高位,而數(shù)字j是從小到大遞增的,因此要通過這種方式保證判斷的順序是從高位(第15位)到低位(第0位),和繪制的順序保持一致。
for(inti=0;idotCount;++i){
varposition=startPos+Offset(0.0,radius*i*2);
for(intj=0;jdotCount;++j){
vardotPosition=startPos+Offset(radius*2*j,position.dy);
if((wordHex[i]((1dotCount-j-1)))!=0){
paint.color=Colors.blue[600]!;
canvas.drawCircle(dotPosition,radius,paint);
}else{
paint.color=Colors.grey;
canvas.drawCircle(dotPosition,radius,paint);
}
繪制的結(jié)果如下所示。
由點(diǎn)聚集成字的動畫實(shí)現(xiàn)
接下來我們來考慮如何實(shí)現(xiàn)開篇說的類似的動畫效果。實(shí)際上方法也很簡單,就是先按照文字應(yīng)該點(diǎn)亮的LED的數(shù)量,先在隨機(jī)的位置繪制這么多數(shù)量的LED,然后通過動畫控制這些LED移動到目標(biāo)位置也就是文字本該繪制的位置。這個移動的計算公式如下,其中t是動畫值,取值范圍為0-1.
需要注意的是,隨機(jī)點(diǎn)不能在繪圖過程生成,那樣會導(dǎo)致每次繪制產(chǎn)生新的隨機(jī)位置,也就是初始位置會變化,導(dǎo)致上面的公式實(shí)際不成立,就達(dá)不到預(yù)期的效果。另外,也不能在build方法中生成,因?yàn)槊看嗡⑿耣uild方法就會被調(diào)用,同樣會導(dǎo)致初始位置發(fā)生變化。所以,生成隨機(jī)位置應(yīng)該在initState方法完成。但是又遇到一個新問題,那就是initState方法里沒有context,拿不到屏幕寬高,所以不能直接生成位置,我們只需要生成一個0-1的隨機(jī)系數(shù)就可以了,然后在繪制的時候在乘以屏幕寬高就得到實(shí)際的初始位置了。初始位置系數(shù)生成代碼如下:
@override
voidinitState(){
super.initState();
varwordBitCount=0;
for(varhexindao){
wordBitCount+=_countBitOne(hex);
startPositions=List.generate(wordBitCount,(index){
returnOffset(
Random().nextDouble(),
Random().nextDouble(),
}
wordBitCount是計算一個字中有多少bit是1的,以便知道要繪制的LED數(shù)量。接下來是繪制代碼了,我們這次對于不亮的直接不繪制,然后要點(diǎn)亮的位置通過上面的位置計算公式計算,這樣保證了一開始繪制的是隨機(jī)位置,隨著動畫的過程,逐步移動到目標(biāo)位置,最終匯聚成一個字,就實(shí)現(xiàn)了預(yù)期的動畫效果,代碼如下。
voidpaint(Canvascanvas,Sizesize){
finaldotCount=16;
finalfontSize=100.0;
varradius=fontSize/dotCount;
varstartPos=
Offset(size.width/2-fontSize,size.height/2-fontSize);
varpaint=Paint()..color=Colors.blue[600]!;
varpaintIndex=0;
for(inti=0;idotCount;++i){
varposition=startPos+Offset(0.0,radius*i*2);
for(intj=0;jdotCount;++j){
//判斷第i行第幾位不為0,不為0則繪制,否則不繪制
if((wordHex[i]((1dotCount-j)))!=0){
varstartX=startPositions[paintIndex].dx*size.width;
varstartY=startPositions[paintIndex].dy*size.height;
varendX=startPos.dx+radius*j*2;
varendY=position.dy;
varanimationPos=Offset(startX+(endX-startX)*animationValue,
startY+(endY-startY)*animationValue);
canvas.drawCircle(animationPos,radius,paint);
paintIndex++;
}
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- GB/T 46848.4-2025技術(shù)產(chǎn)品文件產(chǎn)品設(shè)計數(shù)據(jù)管理要求第4部分:權(quán)限管理
- 貨車司機(jī)安全生產(chǎn)制度
- 行政復(fù)議案件評查制度
- 落實(shí)信息工作相關(guān)制度
- 雷電預(yù)防科普動態(tài)
- 2026廣東佛山順德區(qū)容桂幸福陳占梅小學(xué)招聘語文數(shù)學(xué)臨聘教師招聘2人備考考試題庫附答案解析
- 2026甘肅嘉峪關(guān)市文化館開發(fā)公益性崗位招聘2人備考考試題庫附答案解析
- 2026四川涼山州金陽縣公安局招聘35人備考考試題庫附答案解析
- 2026山東事業(yè)單位統(tǒng)考煙臺萊陽市招聘138人參考考試試題附答案解析
- JIS B 9650-2-2011 食品加工機(jī)械安全及衛(wèi)生通.用設(shè)計準(zhǔn)則.第2部分-衛(wèi)生通.用設(shè)計準(zhǔn)則
- 交通事故培訓(xùn)
- 2026年醫(yī)保藥品目錄調(diào)整
- 2026四川雅安市漢源縣審計局招聘編外專業(yè)技術(shù)人員2人筆試備考試題及答案解析
- 食品銷售業(yè)務(wù)員培訓(xùn)課件
- 2026年學(xué)校意識形態(tài)工作計劃
- 2025年銀行信息科技崗筆試真題及答案
- 山西電化學(xué)儲能項(xiàng)目建議書
- GB/T 46392-2025縣域無障礙環(huán)境建設(shè)評價規(guī)范
- DB32-T 4285-2022 預(yù)應(yīng)力混凝土空心方樁基礎(chǔ)技術(shù)規(guī)程
- 刺殺操課件教學(xué)課件
- 福建省廈門市雙十中學(xué)2026屆數(shù)學(xué)九年級第一學(xué)期期末復(fù)習(xí)檢測模擬試題含解析
評論
0/150
提交評論