Flutter 實現背景圖片毛玻璃效果
theme: v-green highlight: atom-one-dark
持續創作,加速成長!這是我參與「掘金日新計劃 · 6 月更文挑戰」的第4天,點選檢視活動詳情
前言
繼續我們繪圖相關篇章,這次我們來看看如何使用 CustomPaint 實現毛玻璃背景圖效果。毛玻璃背景圖其實就是將圖片進行一定程度的模糊,背景圖經過模糊後更加虛幻,使得前景和後景就會有層次感。相比直接加蒙層的效果來說,毛玻璃看起來更加好看一些。下面是背景圖處理前後的對比,我們的前景圖片的透明度並沒有改變,但是背景圖模糊虛化後,感覺前景更加顯眼了一樣。
本篇涉及如下內容:
- 使用 canvas 繪製圖片。
- 繪製圖片時如何更改圖片的填充範圍。
- 使用 ImageFilter 模糊圖片,實現毛玻璃效果。
使用 canvas 繪製圖片
Flutter 為 canvas
提供了drawImage
方法用於繪製圖片,方法定義如下:
dart
void drawImage(Image image, Offset offset, Paint paint)
其中各個引數說明如下:
image
:dart:ui
中的Image
物件,注意不是Widget
中的Image
,因此繪製的時候需要將圖片資源轉換為ui.Image
物件。下面是轉換的示例程式碼,fillImage 即最終得到的ui.Image
物件。注意轉換需要一定的時間,因此需要使用非同步async
/await
操作。 ```dart Futureinit() async { final ByteData data = await rootBundle.load('images/island-coder.png'); fillImage = await loadImage(Uint8List.view(data.buffer)); }
Future
offset
:繪製圖片的起始位置。paint
:繪圖畫筆物件,在paint
上可以應用各種處理效果,比如本篇要用到的圖片模糊效果。
注意,drawImage
方法無法更改圖片繪製的區域大小,預設就是按圖片的實際尺寸繪製的,所以如果要想保證全屏的背景圖,我們就需要使用另一個繪製圖片的方法。
更改繪製圖片的繪製範圍
Flutter 的 canvas
為繪製圖片提供了一個尺寸轉換方法,即可以通過指定原繪製區域的矩形和目標區域的矩形,將圖片某個區域對映到新的矩形框中繪製。也就是我們甚至可以實現繪製圖片的區域性區域。該方法名為 drawImageRect
,定義如下:
dart
void drawImageRect(Image image, Rect src, Rect dst, Paint paint)
方法的引數比較容易懂,我們來看看 Flutter 的文件說明。
Draws the subset of the given image described by the
src
argument into the canvas in the axis-aligned rectangle given by thedst
argument. 翻譯:通過 src 引數將給定圖片的區域性(subset)繪製到座標軸對齊的目標矩形區域內。
下面是我們將源矩形框設定為實際圖片的尺寸和一半寬高的對比圖,可以看到取一半寬高的只繪製了左上角的1/4區域。實際我們可以定位起始位置來擷取部分割槽域繪製。
毛玻璃效果實現
毛玻璃效果實現和我們上兩篇使用 paint
的 shader
屬性有點類似,Paint 類提供了一個imageFilter
屬性專門用於圖片處理,其中dart:ui
中就提供了ui.ImageFilter.blur
方法構建模糊效果處理的 ImageFilter
物件。方法定義如下:
dart
factory ImageFilter.blur({
double sigmaX = 0.0,
double sigmaY = 0.0,
TileMode tileMode = TileMode.clamp
})
這個方法實際呼叫的是一個高斯模糊處理器,高斯模糊其實就是應用一個方法將畫素點周邊指定範圍的值進行處理,進而實現模糊效果,有興趣的可以自行百度一下。下面的 sigmaX
和 sigmaY
分佈代表橫軸方向和縱軸方向的模糊程度,數值越大,模糊程度越厲害。因此我們可以通過這兩個引數控制模糊程度。
dart
return _GaussianBlurImageFilter(
sigmaX: sigmaX,
sigmaY: sigmaY,
tileMode: tileMode
);
注意,這裡 sigmaX 和 sigmaY 不能同時為0,否則會報錯!這裡應該是如果同時為0會導致除0操作。
下面來看整體的繪製實現程式碼,如下所示:
```dart
class BlurImagePainter extends CustomPainter {
final ui.Image bgImage;
final double blur;
BlurImagePainter({ required this.bgImage, required this.blur, }); @override void paint(Canvas canvas, Size size) { var paint = Paint(); // 模糊的取值不能為0,為0會拋異常 if (blur > 0) { paint.imageFilter = ui.ImageFilter.blur( sigmaX: blur, sigmaY: blur, tileMode: TileMode.mirror, ); }
canvas.drawImageRect(
bgImage,
Rect.fromLTRB(0, 0, bgImage.width.toDouble(), bgImage.height.toDouble()),
Offset.zero & size,
paint,
);
}
``
程式碼其實很短,就是在模糊值不為0的時候,應用
imageFilter進行模糊處理,然後使用
drawImageRect方法確保圖片填充滿整個背景。完整程式碼已經提交至:[繪圖相關程式碼](https://gitee.com/island-coder/flutter-beginner/tree/master/custom_paint),檔名為:
blur_image_demo.dart`。變換模糊值的效果如下動圖所示。
總結
本篇介紹了使用 CustomPaint 實現背景圖模糊,毛玻璃的效果。關鍵點在於 使用 Paint
物件的 imageFilter
屬性,使用高斯模糊應用到圖片上。以後碰到需要模糊背景圖的地方就可以直接上手用啦!
我是島上碼農,微信公眾號同名,這是Flutter 入門與實戰的專欄文章,提供體系化的 Flutter 學習文章。對應原始碼請看這裡:Flutter 入門與實戰專欄原始碼。如有問題可以加本人微信交流,微訊號:
island-coder
。👍🏻:覺得有收穫請點個贊鼓勵一下!
🌟:收藏文章,方便回看哦!
💬:評論交流,互相進步!
- 屌炸天!國外同行這樣用Chat GPT提高Flutter開發的效率!
- Flutter 增強版的頁面懸浮按鈕(FloatingActionButton)
- 介紹一個令強迫症討厭的小紅點元件
- 我用了幾行程式碼就搞定了介面變灰效果
- 不就是一個空白頁,有必要那麼講究嗎?
- 花裡胡哨的文字特效,你學會了嗎?
- 這一篇讓你搞定 Flutter 的資料表格
- 用 Flutter 輕鬆做個紅包介面
- 沉浸式彈層越來越多,開發該怎麼做好彈層體驗?
- 列表的載入過程很重要的!
- 這個表單打死我也不填!
- 例項講述開發中的圖片使用者體驗要點
- C 位出道按鈕的自我獨白
- Flutter 繪製3D效果動畫
- 封裝一個有趣的 Loading 元件
- 普通的載入千篇一律,有趣的 loading 萬里挑一
- 由點匯聚成字的動效炫極了
- 給滅霸點顏色看看
- 來看光影流動之美
- Flutter 實現背景圖片毛玻璃效果