【Flutter 元件集錄】 ImageFiltered 與 ColorFiltered

張風捷特烈發表於2021-08-29
前言:

這是我參與8月更文挑戰的第 29 天,活動詳情檢視:8月更文挑戰。為應掘金的八月更文挑戰,我準備在本月挑選 31 個以前沒有介紹過的元件,進行全面分析和屬性介紹。這些文章將來會作為 Flutter 元件集錄 的重要素材。希望可以堅持下去,你的支援將是我最大的動力~

本系列元件文章列表
1.NotificationListener2.Dismissible3.Switch
4.Scrollbar5.ClipPath6.CupertinoActivityIndicator
7.Opacity8.FadeTransition9. AnimatedOpacity
10. FadeInImage11. Offstage12. TickerMode
13. Visibility14. Padding15. AnimatedContainer
16.CircleAvatar17.PhysicalShape18.Divider
19.Flexible、Expanded 和 Spacer 20.Card21.SizedBox
22.ConstrainedBox23.Stack24.Positioned
25.OverflowBox26.SizedOverflowBox27. DecoratedBox
28. BackdropFilter29.ImageFiltered 與 ColorFiltered

一、ImageFiltered 元件

1. 認識 ImageFiltered 元件

上一篇說了 BackdropFilter 元件,它可以在子元件下方新增一個過濾層,所以此效果無法作用於子元件。而 ImageFiltered 是將 過濾層 放在子元件上方,也就是過濾效果可以作用於子元件上。

它繼承自 SingleChildRenderObjectWidget,必須傳入 imageFilter 引數,型別為 ImageFilter。這和 BackdropFilter 元件中的 imageFilter 是一樣的。


2. ImageFiltered 元件的使用

如下是通過 ImageFiltered 對圖片進行模糊的效果,imageFilter 引數的使用和 BackdropFilter 一樣,這裡不再贅述。

1*12*23*35*5
class ImageFilteredDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ImageFiltered(
            imageFilter: ImageFilter.blur(
              sigmaX: 2,
              sigmaY: 2,
            ),
            child: Image.asset(
                'assets/images/sabar.webp',
                fit: BoxFit.cover,
                width: 150,
                height: 150,
            ),
    );
  }
}
複製程式碼

另外 ImageFiltered 並不侷限於 Image 元件。如下將 FlutterUnit 整體使用 ImageFiltered 進行處理,這樣全應用都會有模糊效果。雖然這麼做沒有什麼太大的意義,只是說明 ImageFiltered 可以處理任意元件。

---
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  //滾動效能優化 1.22.0
  GestureBinding.instance?.resamplingEnabled = true;
  runApp(BlocWrapper(
    child: ImageFiltered(
      imageFilter: ImageFilter.blur(
        sigmaX: 2,
        sigmaY: 2,
      ),
      child: FlutterUnit(),
    ),
  ));
}
複製程式碼

3.ImageFiltered 元件原始碼實現

ImageFiltered 繼承自 SingleChildRenderObjectWidget ,內部維護 _ImageFilterRenderObject 渲染物件來實現新增濾色器功能。


_ImageFilterRenderObject#paint 中建立 ImageFilterLayer 物件 layer,並將傳入的 imageFilter 設定給 layer 。通過 context.pushLayer 新增一個層,實現濾色器功能。


二、ColorFiltered 元件

1.認識 ColorFiltered 元件

ColorFiltered 繼承自 SingleChildRenderObjectWidget,必須傳入 colorFilter 引數,型別為 ImageFilter


2. ColorFiltered 元件的使用

ColorFiltered 有四種構造方式,.srgbToLinearGamma.linearToSrgbGamma 是固定的處理效果;.mode 是通過顏色和混合模式進行著色處理。通過 .matrix 可以進行顏色的矩陣變換。這塊比較複雜,不詳細展開,感興趣的可以看一下《Flutter 繪製指南 - 妙筆生花》 的第八章,有對著色器的詳細介紹。

//srgbToLinearGamma
ColorFiltered(
  colorFilter: ColorFilter.srgbToLinearGamma(),
  child:  Image.asset(
    'assets/images/sabar.webp',
    fit: BoxFit.cover,
    width: 150,
    height: 150,
  ),
)
  
//linearToSrgbGamma
ColorFiltered(
  colorFilter: ColorFilter.linearToSrgbGamma(),
  child:  Image.asset(
    'assets/images/sabar.webp',
    fit: BoxFit.cover,
    width: 150,
    height: 150,
  ),
)
  
//.matrix
ColorFiltered(
  colorFilter: ColorFilter.matrix(<double>[
    1,0,0,0,110,
    0,1,0,0,110,
    0,0,1,0,110,
    0,0,0,1,0
  ]),
  child:  Image.asset(
    'assets/images/sabar.webp',
    fit: BoxFit.cover,
    width: 150,
    height: 150,
  ),
),
複製程式碼

同樣 ColorFiltered 並不侷限於 Image 元件。如下將 FlutterUnit 整體使用 ColorFiltered 進行灰色處理,這樣全應用都會有著色效果,說明 ColorFiltered 可以處理任意元件。這在某些場景下還是非常有用的。

---
ColorFiltered(
  colorFilter: ColorFilter.matrix(<double>[
    0.2126, 0.7152, 0.0722, 0, 0,
    0.2126, 0.7152, 0.0722, 0, 0,
    0.2126, 0.7152, 0.0722, 0, 0,
    0,      0,      0,      1, 0,
  ]),
  child: FlutterUnit(),
),
複製程式碼

其實有了 matrix 可以操作顏色變換,就會有很多可發揮的空間,它又可以作用於任何元件,做出全域性的懷舊色什麼的也不是不可以。matrix 這東西,有著無限的可能。


3.ColorFiltered 元件原始碼實現

可能會有人擔心效能什麼的,其實看了這麼多的 SingleChildRenderObjectWidget ,我們也能知道一些特點。ColorFiltered 是通過 _ColorFilterRenderObject 實現的。

在繪製時新增了一層 ColorFilterLayer ,進行著色處理。這就像是在眼前放一個紅色的膜片,看到世界上所有的東西都帶紅色一樣,而不是膜片擁有改變世界的能力,把世界上所有的東西真正被染成了紅色。

ColorFiltered 也是一樣,它只是一個遮罩層,並非所有的元件都一一被染成紅色,不用顧慮太多。OpacityClipRectTransform 這類功能性的元件都是通過新增對應的層實現功能的,所以 ColorFilterLayer 也就是一個普通的 SingleChildRenderObjectWidget

那本文到這裡就結束了,謝謝觀看,明天見~

相關文章