Android利用Flutter實(shí)現(xiàn)立體旋轉(zhuǎn)效果
前言
之前我們提到了 CustomPaint er 的 Paint 可以使用漸變(GradientShader)來填充繪制的圖形,本篇我們來介紹使用圖片填充,并且配合動(dòng)畫實(shí)現(xiàn)“立體”旋轉(zhuǎn)效果,之所以給“立體”加上引號(hào),是因?yàn)閷?shí)際是通過填充圖片自身的光影效果旋轉(zhuǎn)后看起來像是立體效果一樣。下面是實(shí)現(xiàn)的效果圖。

ImageShader 簡(jiǎn)介
ImageShader 的定義如下,我們來看看各個(gè)參數(shù)的用途。
image:用于填充的圖像,是Image類,注意這個(gè)Image類定義在dart:ui庫中,并不是我們用于構(gòu)建圖像組件的Widget下面的Image類。tmx:圖形在 x 軸的處理方式,即當(dāng)被填充的寬度與圖片寬度不匹配時(shí),在橫軸方向如何填充。tmy:圖形在y 軸的處理方式,即當(dāng)被填充的高度與圖片高度不匹配時(shí),在縱軸方向如何填充。matrix4:對(duì)填充圖像的三維空間的平移、旋轉(zhuǎn)等變換操作。filterQuality:當(dāng)圖片尺寸和被填充圖形的尺寸不一致時(shí),采樣的質(zhì)量,有高(high)、中 (medium)、低(low)三類。
ImageShader(
Image image,
TileMode tmx,
TileMode tmy,
Float64List matrix4,
{
FilterQuality? filterQuality,
}
)
tmx 和 tmy 是 TileMode 枚舉,有以下幾種取值:
clamp:圖片不能完整填充圖形時(shí),使用最接近圖形邊緣的顏色進(jìn)行填充,其實(shí)就是邊緣的延伸。比如同時(shí)這是 tmx 和 tmy 都為 TileMode.clamp 的時(shí)候的效果圖如下。

repeated:這個(gè)好理解,就是在各自方向重復(fù)。

decal:就是這個(gè)方向不做任何處理,使用透明填充,比如我們將上面的 tmy 改成 decal,就只會(huì)在 x 軸重復(fù)了。

mirror:顧名思義,就是鏡像填充,下面是 tmx 為 mirror,tmy 為 repeated的效果圖。

構(gòu)建 ui.Image對(duì)象
要使用 ImageShader,我們首先要從圖片資源中構(gòu)建ui.Image 對(duì)象。這需要將圖片文件按ByteData 二進(jìn)制方式讀取,在將二進(jìn)制文件解碼成為 ui.Image 對(duì)象。這個(gè)操作是異步的,因此在操作沒完成前不能使用圖像資源,我們?cè)O(shè)置了一個(gè)isImageLoaded布爾值標(biāo)識(shí)圖像是否加載完成。
final ByteData data = await rootBundle.load('images/beauty.jpg');
fillImage = await loadImage(Uint8List.view(data.buffer));
Future<ui.Image> loadImage(Uint8List img) async {
final Completer<ui.Image> completer = Completer();
ui.decodeImageFromList(img, (ui.Image img) {
setState(() {
isImageLoaded = true;
});
return completer.complete(img);
});
return completer.future;
}
使用 ImageShader 填充形狀
使用 ImageShader 填充和 GradientShader 類似,按我們上面說的參數(shù)構(gòu)建一個(gè) ImageShader 對(duì)象就可以了,代碼如下。注意,Paint 對(duì)象的填充方式必須是 fill,如果是空心的話是看不到效果的。
@override
void paint(Canvas canvas, Size size) {
var paint = Paint();
paint.style = PaintingStyle.fill;
paint.shader = ImageShader(
image,
TileMode.mirror,
TileMode.repeated,
Matrix4.identity().storage,
filterQuality: FilterQuality.high,
);
canvas.drawRect(Rect.fromLTRB(0, 0, size.width, size.height), paint);
}
立體旋轉(zhuǎn)效果實(shí)現(xiàn)
立體效果需要利用填充圖像的光影效果,因此我們需要找一張圖片,比如明暗不同,或色彩不同的,這樣旋轉(zhuǎn)起來就會(huì)感覺是立體的。旋轉(zhuǎn)的話使用 Matrix4的旋轉(zhuǎn)變換就行。同時(shí),為了讓旋轉(zhuǎn)過程展示的圖像不固定,我們旋轉(zhuǎn)的時(shí)候可以通過Matrix4的平移顯示不同圖形的區(qū)域。下面是我們用于測(cè)試的兩張圖片。


實(shí)現(xiàn)的代碼如下所示,其中animationValue是動(dòng)畫過程中 Animation 對(duì)象的值,我們的動(dòng)畫時(shí)長(zhǎng)設(shè)置為10秒。這里我們繪制的其實(shí)是一個(gè)圓形,只是因?yàn)樘畛鋱D像在不停的旋轉(zhuǎn),且展示的圖像不同就看起來有了立體效果。
void paint(Canvas canvas, Size size) {
var paint = Paint();
paint.style = PaintingStyle.fill;
paint.shader = ImageShader(
image,
TileMode.mirror,
TileMode.mirror,
(Matrix4.identity()
..translate(5 * animationValue, 5 * animationValue)
..scaled(0.5)
..rotateZ(2 * pi * animationValue))
.storage,
filterQuality: FilterQuality.high,
);
Offset center = Offset(size.width / 2, size.height / 2);
canvas.drawCircle(center, 200, paint);
}
下圖是換了星球圖片的運(yùn)行效果,大家也可以調(diào)整 ImageShader 的參數(shù)看看其他參數(shù)的效果。

總結(jié)
源碼已經(jīng)提交至:繪圖相關(guān)源碼,文件名為:image_shader_demo.dart。本篇介紹了 Flutter 繪圖使用 ImageShader 填充圖形,并且利用 Matrix4的三維變換加上動(dòng)畫實(shí)現(xiàn)了立體旋轉(zhuǎn)的動(dòng)畫效果。隨著對(duì) Flutter 繪圖的深入,我們會(huì)發(fā)現(xiàn)繪圖覆蓋的面非常廣,也能夠?qū)崿F(xiàn)更多有趣的效果。
以上就是Android利用Flutter實(shí)現(xiàn)立體旋轉(zhuǎn)效果的詳細(xì)內(nèi)容,更多關(guān)于Android Flutter立體旋轉(zhuǎn)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Android?Flutter實(shí)現(xiàn)搜索的三種方式詳解
- Android Flutter圖片處理之高斯模糊的實(shí)現(xiàn)
- Android使用Flutter實(shí)現(xiàn)錄音插件
- Android?Flutter繪制有趣的?loading加載動(dòng)畫
- Android Flutter利用CustomPaint繪制基本圖形詳解
- Android Flutter制作交錯(cuò)動(dòng)畫的示例代碼
- Android Flutter表格組件Table的使用詳解
- Android Flutter實(shí)現(xiàn)GIF動(dòng)畫效果的方法詳解
- Android Flutter實(shí)現(xiàn)原理淺析
相關(guān)文章
Android控件PullRefreshViewGroup實(shí)現(xiàn)下拉刷新和上拉加載
這篇文章主要為大家詳細(xì)介紹了Android控件PullRefreshViewGroup實(shí)現(xiàn)下拉刷新和上拉加載效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
Android 沉浸式改變小米魅族狀態(tài)欄顏色的實(shí)例代碼
這篇文章主要介紹了Android 沉浸式改變小米魅族狀態(tài)欄顏色的實(shí)例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02
Flutter Android應(yīng)用啟動(dòng)白屏的解決方案
任何一個(gè)app基本都會(huì)設(shè)計(jì)一個(gè)啟動(dòng)頁,今天我們就來看看怎么在flutter項(xiàng)目中設(shè)置啟動(dòng)頁,這篇文章主要給大家介紹了關(guān)于Flutter Android應(yīng)用啟動(dòng)白屏解決的相關(guān)資料,需要的朋友可以參考下2021-11-11
Android5.0多種側(cè)滑欄效果實(shí)例代碼
這篇文章主要介紹了Android5.0多種側(cè)滑欄效果實(shí)例代碼的相關(guān)資料,本文圖文并茂介紹的非常詳細(xì),需要的朋友可以參考下2016-09-09
Android onSaveInstanceState和onRestoreInstanceState觸發(fā)的時(shí)機(jī)
這篇文章主要介紹了Android onSaveInstanceState和onRestoreInstanceState觸發(fā)的時(shí)機(jī)的相關(guān)資料,需要的朋友可以參考下2017-05-05
Android ContentProvider獲取手機(jī)聯(lián)系人實(shí)例
這篇文章主要介紹了Android ContentProvider獲取手機(jī)聯(lián)系人實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
Android自定義view繪制圓環(huán)占比動(dòng)畫
這篇文章主要為大家詳細(xì)介紹了Android自定義view繪制圓環(huán)占比動(dòng)畫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01

