網站首頁 編程語言 正文
前言
上一篇我們介紹了?Animation
?和?AnimationController
?的使用,這是最基本的動畫構建類。但是,如果我們想構建一個可復用的動畫組件,通過外部參數來控制其動畫效果的時候,上一篇的方法就不太合適了。在 Flutter 中提供了?AnimatedWidget
?組件用于構建可復用的動畫組件。本篇我們用?AnimatedWidget
?來實現組件的3D 旋轉效果,如下圖所示。
AnimatedWidget 簡介
AnimatedWidget
是一個抽象的?StatefulWidget
, 構造方法如下所示。
const?AnimatedWidget({ ????Key??key, ????required?this.listenable, ??})?:?assert(listenable?!=?null), ???????super(key:?key);
主要在于接收一個?listenable
?參數,通常會是?Animation
?對象。在?AnimatedWidget
?內部的_AnimatedState
?類中,會添加該對象變化監聽回調,進而刷新界面。
class?_AnimatedState?extends?State?{ ??@override ??void?initState()?{ ????super.initState(); ????widget.listenable.addListener(_handleChange); ??} ??@override ??void?didUpdateWidget(AnimatedWidget?oldWidget)?{ ????super.didUpdateWidget(oldWidget); ????if?(widget.listenable?!=?oldWidget.listenable)?{ ??????oldWidget.listenable.removeListener(_handleChange); ??????widget.listenable.addListener(_handleChange); ????} ??} ??@override ??void?dispose()?{ ????widget.listenable.removeListener(_handleChange); ????super.dispose(); ??} ??void?_handleChange()?{ ????setState(()?{ ??????//?The?listenable's?state?is?our?build?state,?and?it?changed?already. ????}); ??} ?? ??//?... }
可以看到,只需要將?Animation
?對象傳給?AnimatedWidget
?對象后,就不需要我們之前那樣自己寫?addListener
?之類的處理了。而整個動畫可以交給外部其他對象來控制,從而實現動畫組件的復用。
3D 旋轉動畫的實現
3D 旋轉的實現比較簡單,在?Container
?組件有兩個參數控制轉換(transform),分別是:
-
transform
:Matrix4
對象,可以實現圍繞 X、Y、Z軸的旋轉、平移,以及變形等效果。關于?Matrix4
涉及到很多矩陣運算和線性代數的知識,可以參考 Matrix4的源碼自行溫習一下大學的數學知識。 -
transformAlignment
:轉換的對齊方式,可以理解為起點位置,可以使用?Alignment
?對象來設置。
有了這個基礎,我們就可以定義3D 旋轉動效了,我們定義一個通用的組件,ThreeDAnimatedWidget
:
class?ThreeDAnimatedWidget?extends?AnimatedWidget?{ ??final?Widget?child; ??const?ThreeDAnimatedWidget( ??????{Key??key,?required?Animation?animation,?required?this.child}) ??????:?super(key:?key,?listenable:?animation); ??@override ??Widget?build(BuildContext?context)?{ ????final?animation?=?listenable?as?Animation ; ????return?Center( ??????child:?Container( ????????transform:?Matrix4.identity() ??????????..rotateY(2?*?pi?*?animation.value) ??????????..setEntry(1,?0,?0.01), ????????transformAlignment:?Alignment.center, ????????child:?child, ??????), ????); ??} }
這里我們設置的是圍繞中心點繞 Y 軸旋轉,并使用?setEntry
?設置了一定的傾斜角 (這會更有立體感)。實際我們也可以設置圍繞 X 軸或 Z 軸旋轉。接下來就是這個動畫組件的應用了,我們構建一個帶有陰影的文字(看起來像立體字)作為這個動畫的子組件,其他的控制和上一篇的是類似的,完整代碼如下:
class?AnimatedWidgetDemo?extends?StatefulWidget?{ ??const?AnimatedWidgetDemo({Key??key})?:?super(key:?key); ??@override ??_AnimatedWidgetDemoState?createState()?=>?_AnimatedWidgetDemoState(); } class?_AnimatedWidgetDemoState?extends?State ????with?SingleTickerProviderStateMixin?{ ??late?Animation?animation; ??late?AnimationController?controller; ??@override ??void?initState()?{ ????super.initState(); ????controller?= ????????AnimationController(duration:?const?Duration(seconds:?3),?vsync:?this); ????animation?=?Tween (begin:?0.0,?end:?1.0).animate(controller); ??} ??@override ??Widget?build(BuildContext?context)?{ ????return?Scaffold( ??????appBar:?AppBar( ????????title:?Text('AnimatedWidget?動畫'), ??????), ??????body:?ThreeDAnimatedWidget( ????????animation:?animation, ????????child:?Text( ??????????'島上碼農', ??????????style:?TextStyle( ????????????fontSize:?42.0, ????????????color:?Colors.blue, ????????????fontWeight:?FontWeight.bold, ????????????shadows:?[ ??????????????Shadow( ??????????????????blurRadius:?2, ??????????????????offset:?Offset(2.0,?1.0), ??????????????????color:?Colors.blue[900]!), ????????????], ??????????), ????????), ??????), ??????floatingActionButton:?FloatingActionButton( ????????child:?Icon(Icons.play_arrow,?color:?Colors.white), ????????onPressed:?()?{ ??????????if?(controller.status?==?AnimationStatus.completed)?{ ????????????controller.reverse(); ??????????}?else?{ ????????????controller.forward(); ??????????} ????????}, ??????), ????); ??} ??@override ??void?dispose()?{ ????controller.dispose(); ????super.dispose(); ??} }
可以看到,這個?ThreeDAnimatedWidget
?可以做到復用了,在需要這樣動效的場景里,按照上面的方式給它傳入?Animation
?對象和子組件就可以了。例如我們將文字修改為一張圖片。
//... body:?ThreeDAnimatedWidget( ??animation:?animation, ??child:?Image.asset( ????'images/avatar.jpg', ????width:?100, ????height:?100, ??), ), //...
圖片旋轉.gif
總結
本篇介紹了?AnimatedWidget
?的使用,通過?AnimatedWidget
?可以構建可復用的動畫組件。同時,還通過?Container
?的?transform
?屬性加上?AnimatedWidget
?實現了三維空間的旋轉效果。實際開發過程中,我們可以基于?AnimatedWidget
?構建很多個性化的、可復用的動畫組件,提升應用的趣味性。
原文鏈接:https://mp.weixin.qq.com/s/944KqcX3uoDdB3Q18VbrRw
相關推薦
- 2022-04-28 關于k8s中subpath的使用詳解_云其它
- 2023-02-26 nvidia-smi命令詳解和一些高階技巧講解_linux shell
- 2022-03-29 python實現二叉排序樹_python
- 2022-11-03 刪除?Tomcat?webapps?目錄自帶項目方式詳解_Tomcat
- 2022-05-22 Nginx圖片服務器配置之后圖片訪問404的問題解決_nginx
- 2021-12-02 golang配制高性能sql.DB的使用_Golang
- 2023-02-01 python?multiply()與dot使用示例講解_python
- 2022-07-27 Python編寫條件分支代碼方法_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支