Flutter 工程化框架選擇——搞定 Flutter 動畫

語言: CN / TW / HK

theme: smartblue

! 本文為稀土掘金技術社群首發簽約文章,14天內禁止轉載,14天后未獲授權禁止轉載,侵權必究!

首先,這次會寫一個新的系列《Flutter 工程化框架選擇》,但是系列其實並非前端的工程治理方面的內容,這個系列只是單純告訴你,建立一個 Flutter 工程,或者說搭建一個 Flutter 工程腳手架,應該如何選擇快速適合自己的外掛模組,或者說這是一個指引系列,相信會適合新手同學

為什麼會想要寫一個這樣的系列?因為這類的問題太多了,簡單檢索一個群的聊天記錄,單單 有沒有 這個關鍵字就可以搜尋翻好幾頁,所以這個系列的目的,是幫大家整理 Flutter 工程裡可能會需要的各種第三方模組,並對比一些技術細節,也是方便以後回答問題我可以直接甩連結

首先作為系列第一篇文章,本篇我們先聊動畫。

為什麼第一篇聊它,因為近期剛好做了一些關於 Flutter 動畫的調研,不久前也剛好釋出過一些關於它的內容,所以素材比較多,而本篇將針對你可能會遇到的動畫場景,給你推薦各式各樣的動畫框架來加速開發

前言

在之前的 Flutter 小技巧 系列裡我們聊過,如果沒有使用封裝, Flutter 裡建立動畫一般需要:

  • AnimationController : 用於控制動畫啟動、暫停
  • TickerProvider : 用於建立 AnimationController 所需的 vsync 引數,一般最常使用 SingleTickerProviderStateMixin
  • Animation : 用於處理動畫的 value ,例如常見的 CurvedAnimation
  • 接收動畫的物件:例如 FadeTransition

這種寫法如下程式碼所示,我們一般可以稱為顯式動畫(不要糾結名詞叫法),大致特徵就是:以 *Transition 命名,比如 FadeTransitionSizeTransitionRotationTransition 等,需要我們自己定義和操作 AnimationController

```dart class _AnimatedOpacityState extends State with TickerProviderStateMixin { late final AnimationController _controller = AnimationController( duration: const Duration(seconds: 2), vsync: this, )..repeat(reverse: true); late final Animation _animation = CurvedAnimation( parent: _controller, curve: Curves.easeIn, );

@override void dispose() { _controller.dispose(); super.dispose(); }

@override Widget build(BuildContext context) { return Container( color: Colors.white, child: FadeTransition( opacity: _animation, child: const Padding(padding: EdgeInsets.all(8), child: FlutterLogo()), ), ); } } ```

但是,如果都採用這種方式去使用動畫,那麼專案裡就會存在很多的重複程式碼,所以 Flutter 官方預設提供了一些動畫封裝,也可以叫做隱式動畫(不要糾結名詞叫法):

也就是開箱即用,常見是 Animated* 開頭的 Widget,例如 AnimatedPositionedAnimatedContainerAnimatedPaddingAnimatedOpacity 等控制元件,它們最大的特點就是內部已經完全封裝好邏輯,你只需要配置對應引數就可以觸發動畫。

如下程式碼所示,你只需要改變 _width_height 就可以觸發動畫效果,動畫中間過程的資料會通過 Curves 變化的 “插值” 來得到。

dart body: Center( child: AnimatedContainer( width: _width, height: _height, decoration: BoxDecoration( color: _color, borderRadius: _borderRadius, ), duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn, ), ),

雖然隱式動畫挺方便,但真正的專案裡可能很多情況還是不滿我們的需求,往往業務邏輯會需要更靈活或者更細緻的封裝,那麼這就要聊到本篇後面的內容。

基礎動畫

說到基礎動畫的部分,主要就是在隱式動畫的基礎上進一步的封裝,可以通過簡單配置快速實現一些更精緻的動畫效果。

animations

animations 是官方封裝的動畫庫,主要賣點在於 Material 風格的動畫過渡,所以這個庫的核心重點是路由過渡動畫或者頁面切換動畫,例如下圖就是 Demo 裡利用庫裡自帶的 OpenContainer 實現頁面跳轉的 Material 過渡 效果。

另外也可以使用 PageTransitionSwitcher 實現一些非路由的頁面切換動畫,可以理解為是一個變異版本的 AnimatedSwitcher ,或者是 Stack 版動畫 PageView ,不過支援自定義進入和退出動畫,還可以支援自定義佈局,一般預設使用預設 defaultLayoutBuilder 的話,就是使用 Stack 作為佈局。

官方 Demo 裡也會使用 PageTransitionSwitcher 來做步進頁面跳轉的效果,所以 animations 的核心動畫能力主要是在於頁面過渡方面

總的來說,這個庫是官方維護,值得信賴。

simple_animations

simple_animations 如同它的名字所示,它主要是簡化了自定義動畫的過程,正如前面所示,在 Flutter 裡使用動畫,我們一般需要定義 AnimationControllerAnimatableAnimation 等物件來配置動畫效果。

而 simple_animations 提供了 AnimationMixin 物件,如下程式碼所示,你只需要通過 with 關鍵字就可以簡化接入動畫的程式碼。

| | | | | ------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------- |

同時 simple_animations 也提供了各種 Builder 來簡化,例如使用 MirrorAnimationBuilder 就可以實現一個迴圈反覆的動畫效果。

所以 simple_animations 針對顯式動畫進行了優化封裝,在更方便的情況下做到能更靈活控制動畫效果,如下圖所示,在 gsy_fluter_demo 裡就利用了 simple_animations 來實現一些動畫效果:

  • MirrorAnimationMovieTween 實現漸變的背景
  • LoopAnimationMovieTween 實現了粒子動畫

| | | | ---------------------------------------- | ------------------------------------------ |

不過這個庫有個小問題,就是它最近幾次大版本,每個版本總是會有一些 break change ,但是可能就是改改名字,換換引數位置,如果你一段時間沒關注,再升級可能會有些成本。

animate_do

animate_do 是一個輕量級動畫包,它比 simple_animations “更懶”,程式碼也相對簡單很多,內部提供了豐富的動畫封裝 Widget 可直接使用

你可以理解為更豐富的隱式動畫。

animate_do 就是通過 AnimatedBuilder 配合 TransformOpacity 進行了封裝,然後開發者可以通過 FlipInXFadeInDownElasticIn 等物件直接實現動畫效果。

既然 animate_do 十分簡單,那為什麼會推薦它呢?因為它真的很實用。

首先簡單代表著好維護,作者不玩了我們自己也能接,其次 animate_do 提供了相當豐富的封裝,這對於懶人來說它真的很實用,特別是對於一些 “相對複雜” 的動畫效果上(如下圖3)可以節省很多時間,特別是在 TweenCurvedAnimation的封裝上。

| | | | | --------------------------------------- | ----------------------------------------- | --------------------------------------- |

目前有一段時候沒更新,但是問題不大~ 同類型的庫還有 spring ,可以作為替代專案,也實現了類似的封裝。

UI 動畫

介紹完基礎動畫效果,接下來推薦一些常用的動畫框架,因為經常有人問到有沒有xxx 的實現可以直接拿來使用,秉承著有做好的就不自己動手原則,下面這些 UI 動畫框架,也許在你開發過程中就會需要用到。

UI 動畫部分就不介紹實現了,主要就看功能符不符合你需求。

數字動畫

首先是數字動畫,常見的有 flutter-animated-counter ,本身它就提供了豐富的 API 和動畫效果,類似的第三方庫還有 odometeranimated_digit 等,具體可以自己按需選擇。

| | | | | ------------------------------------------- | ------------------------------------------- | ----------------------------------------- |

跑馬燈

既然聊到文字動畫,就不得不說跑馬燈,如下表格所示是 Flutter 裡常用到的文字跑馬燈的第三方 package ,其中 marquee_widget 提供的介面相對更佳豐富。

| marquee_widget | text_scroll | marquee_text | | ----------------------------------------------------------- | ------------------------------------------------------------ | ----------------------------------------------------- | | | | |

載入動畫

載入動畫是最常見的 UI 動畫,如果你沒有設計師,如果你不知道 loading 動畫用什麼好,那你可以考慮下面幾個 package,這三個 loading 庫都是純程式碼實現,提供了豐富的樣式選擇。

| flutter_spinkit | loading_animation_widget | loading_indicator | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | | | |

純程式碼實現有什麼好處?當樣式需要做一些簡單調整時,作為開發者可以通過程式碼快速修改,這是我喜歡純程式碼實現動畫的原因。

指引動畫

指引動畫也是常見的需求之一,基本實現都會通過 Overlay 來完成,不同的可能就是動畫效果和定位方式的差異,具體也可以按照自己的需要選擇。

| feature_discovery | flutter_showcaseview | flutter_intro | BubbleShowcase | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------- | ---------------------------------------------------------- | | | | | |

列表動畫

列表動畫也是常見的 UI 動畫能力之一,基本上 Flutter 上最常見用都的第三方列表動畫庫就是下面表格裡這三個,坑還是有的,但是“又不是不能用”。

| flutter_staggered_animations | animation_list | transformable_list_view | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | | | |

3D 立體動畫

這個類目可能關注的人反而不是很多,但是恰好是我近期比較關注的動畫實現,這裡主要推薦兩個利用矩陣變換繪製 3D 視覺效果的第三方庫,它們不同在於:

  • zwidget 能力相對比較弱,直接使用的是 Transform 的能力
  • zflutter 來源於前端 zdog 專案,是直接對 Canvaspath 進行矩陣變換

| zflutter | zwidget | | --------------------------------------------------- | ------------------------------------------------------ | | | |

在不久前我也寫過一篇文章 《Flutter 實現 “真” 3D 動畫效果》,內容主要分析了 zflutter 的實現邏輯和如何使用 zflutter ,利用純程式碼渲染 3D 效果的動畫。

當然,上門兩個 3D 動畫,它們在使用上相對會比較複雜,如果需要更高階的動畫效果,建議看下面的推薦。

高階動畫支援

介紹完面向程式設計師的動畫支援之後,最後我們來介紹兩個面向設計師的動畫支援庫,同時也是更好支援複雜動畫實現的庫。

Lottie

Lottie 相信大家不會陌生,airbnb 最優秀的動畫開源庫,設計師可以通過 AE 外掛匯出設計好的動畫效果,然後利用平臺的 Canvas 等能力渲染出 AE 上的動畫效果。

使用 Lottie 的好處在於,設計師可以更自由的去嘗試更炫酷的動畫,而程式設計師只需要關心如何控制動畫(時長,迴圈,方向,幀率等),同時因為動畫大部分時候都是向量資料,所以 Lottie 檔案相對不大。

在早期的時候,由於 Lottie 本身只支援原生平臺,所以 Flutter 上都是通過外界紋理或者 PlatformView 等形式接入,這樣的後果就是導致各種效能和相容問題,好在現在 lottie-flutter 已經支援 Dart Canvas 的原生 API 。

當然, Lottie 本身的問題也很明顯,那就是你的互動設計師要會 AE ,很遺憾的是,我接觸的大部分設計師都不會 AE ,而且會 AE 還不夠,還需要會 Bodymovin 外掛相關的相容,熟悉什麼屬性可以用,整體開發環境也比較重。

Rive

對於 rive 可能大家會感覺比較陌生,而做過 Flutter 開發的可能對 rive 會有所耳聞,因為 rive 在此之前叫 flare ,是 2dimensions 公司的開源動畫產品,在釋出之初由於和 Flutter 團隊有深入合作,所以在初期一直是 Flutter 官方推薦的動畫框架。

| | | | ------------------------------------------------------- | ------------------------------------------------------- |

rive 同樣是一個面向設計師的動畫框架,只不過他是在 Web Editor 裡進行 UI 編排和動畫繪製,所以他在開發環境上相對會輕量化。

| | img | img | | ------------------------------------------- | ---------------------------------------------------------- | ----------------------------------------------------------- |

同時 rive 同樣是通過匯出向量的動畫資料檔案(也可以包含一些靜態資源),然後利用平臺的 Canvas 來實現動畫效果,所以它的佔用提及也不會很大。

另外 rive 現在也是全平臺支援, Android、 iOS、Web、Desktop、Flutter 、React、Vue、C++ 等都在支援範圍之內。

如果想深入瞭解 rive ,也可以看我之前的 《給掘金 Logo 快速新增動畫效果》 ,其實對於程式設計師來說,rive 同時很好上手。

目前 rive 的問題是,第二代 rive 和第一代 flare 存在斷檔不相容,而且基本可以忽略遷移的可能,同時沒有本地化免費開發 IDE 有時候也是一種麻煩。

好了,關於 Flutter 動畫相關的內容推薦就到這裡,如果你還有什麼關於 Flutter 工程或者框架的疑問,歡迎留言評論,也許又可以多一期的素材~