日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Android?Flutter實現3D動畫效果示例詳解_Android

作者:島上碼農 ? 更新時間: 2022-05-26 編程語言

前言

上一篇我們介紹了?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),分別是:

  • transformMatrix4對象,可以實現圍繞 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

欄目分類
最近更新