
動畫運作的原理
任何程式的動畫原理都是一樣的,即:視覺暫留,視覺暫留又叫視覺暫停,人眼在觀察景物時,光信号傳入大腦神經,需經過一段短暫的時間,光的作用結束後,視覺形象并不立即消失,這種殘留的視覺稱“後像”,視覺的這一現象則被稱為“視覺暫留”。
電影就是依靠視覺暫留,在感官上電影是連續的。使動畫有流暢的感覺,幀率至少要達到24幀,即:每秒播放24個圖像,是以動畫有一個非常關鍵的性能參數FPS(Frame Per Second),即幀率,達到24fps,畫面就比較流暢了,Flutter的FPS理論上可以達到60fps,超過48fps,将會感到絲滑般的順暢。
Flutter動畫系統
為了友善開發者進行動畫的開發,Flutter将動畫系統進行封裝,抽象出4個概念:Animation、Curve、AnimationController、Tween。
- Animation:Flutter動畫中的核心類,此類是抽象類,通常情況下使用其子類:AnimationController,可以擷取目前動畫的狀态和值,也可以添加其狀态變化監聽和值變化監聽。
- Curve:決定動畫執行的曲線,和Android中的Interpolator(內插補點器)是一樣的,負責控制動畫變化的速率,系統已經封裝了10多種動畫曲線,詳見
類。Curves
- AnimationController:動畫控制器,控制動畫的開始、停止。繼承自Animation。
- Tween:映射生成不同範圍的值,AnimationController的動畫值是double類型的,如果需要顔色的變化,Tween可以完成此工作。
将Container控件的大小由100變為300,代碼如下:
class AnimationDemo extends StatefulWidget {
@override
State<StatefulWidget> createState() => _AnimationDemo();
}
class _AnimationDemo extends State<AnimationDemo>
with SingleTickerProviderStateMixin {
AnimationController _animationController;
@override
void initState() {
_animationController = AnimationController(
duration: Duration(seconds: 2),
lowerBound: 100.0,
upperBound: 300.0,
vsync: this);
_animationController.addListener(() {
setState(() {});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: <Widget>[
RaisedButton(
child: Text('開始動畫'),
onPressed: () {
_animationController.forward();
},
),
Expanded(
child: Center(
child: Container(
width: _animationController.value,
height: _animationController.value,
color: Colors.red,
),
),
),
],
),
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
}
AnimationController
的初始化中
vsync
,這個參數要說明白能說一天,我們隻需先記住其寫法,
this
表示
SingleTickerProviderStateMixin
,螢幕每一幀都會引起
AnimationController
值的變化。
dispose
方法中要記住釋放
AnimationController
。
UI的更新是通過
setState
更新的,
_animationController.addListener(() {
setState(() {});
});
效果如下:
預設情況下,動畫曲線為線性,修改動畫曲線如下:
class _AnimationDemo extends State<AnimationDemo>
with SingleTickerProviderStateMixin {
AnimationController _animationController;
Animation _animation;
@override
void initState() {
_animationController = AnimationController(
duration: Duration(seconds: 2),
vsync: this);
_animationController.addListener(() {
setState(() {});
});
_animation = CurvedAnimation(parent: _animationController,curve: Curves.easeIn);
_animation = Tween(begin: 100.0,end: 300.0).animate(_animation);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: <Widget>[
RaisedButton(
child: Text('開始動畫'),
onPressed: () {
_animationController.forward();
},
),
Expanded(
child: Center(
child: Container(
width: _animation.value,
height: _animation.value,
color: Colors.red,
),
),
),
],
),
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
}
修改的地方說明如下:
- AnimationController中
和lowerBound
不能在直接設定為100和300,因為AnimationController需要被CurvedAnimation使用,值的範圍必須是0-1。upperBound
- 由于AnimationController值的範圍是0-1,而動畫需要在100-300變化,是以引入Tween。
如果動畫是顔色的變化,修改如下:
_animation = ColorTween(begin: Colors.red,end: Colors.blue).animate(_animation);
對動畫狀态監聽:
_animationController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
//執行結束反向執行
_animationController.reverse();
} else if (status == AnimationStatus.dismissed) {
//反向執行結束正向執行
_animationController.forward();
}
});
動畫狀态:
- dismissed:動畫結束,停在開始處。
- forward:動畫正向進行。
- reverse:動畫反向進行。
- completed:動畫結束,停在末尾處。
上面就是動畫的基本用法,有沒有發現一些通用的地方:
- 每次重新整理UI都需要調用
setState
“懶”是原罪,也是社會進步的最大動力。
Flutter封裝了AnimatedWidget,此控件就封裝了
setState
。雖然Flutter為封裝了大量的動畫控件,但萬變不離其宗。
Flutter 25種動畫元件介紹
Flutter中提供了大量的動畫元件及詳細用法:
- AnimatedBuilder: http://laomengit.com/flutter/widgets/AnimatedBuilder/
- AlignTransition: http://laomengit.com/flutter/widgets/AlignTransition/
- AnimatedOpacity: http://laomengit.com/flutter/widgets/AnimatedOpacity/
- AnimatedAlign: http://laomengit.com/flutter/widgets/AnimatedAlign/
- AnimatedPadding: http://laomengit.com/flutter/widgets/AnimatedPadding/
- AnimatedCrossFade: http://laomengit.com/flutter/widgets/AnimatedCrossFade/
- AnimatedContainer: http://laomengit.com/flutter/widgets/AnimatedContainer/
- AnimatedPositioned: http://laomengit.com/flutter/widgets/AnimatedPositioned/
- AnimatedPositionedDirectional: http://laomengit.com/flutter/widgets/AnimatedPositionedDirectional/
- AnimatedSwitcher: http://laomengit.com/flutter/widgets/AnimatedSwitcher/
- AnimatedIcon: http://laomengit.com/flutter/widgets/AnimatedIcon/
- TweenAnimationBuilder: http://laomengit.com/flutter/widgets/TweenAnimationBuilder/
- DecoratedBoxTransition: http://laomengit.com/flutter/widgets/DecoratedBoxTransition/
- DefaultTextStyleTransition: http://laomengit.com/flutter/widgets/DefaultTextStyleTransition/
- AnimatedDefaultTextStyle: http://laomengit.com/flutter/widgets/AnimatedDefaultTextStyle/
- PositionedTransition: http://laomengit.com/flutter/widgets/PositionedTransition/
- RelativePositionedTransition: http://laomengit.com/flutter/widgets/RelativePositionedTransition/
- RotationTransition: http://laomengit.com/flutter/widgets/RotationTransition/
- ScaleTransition: http://laomengit.com/flutter/widgets/ScaleTransition/
- SizeTransition: http://laomengit.com/flutter/widgets/SizeTransition/
- SlideTransition: http://laomengit.com/flutter/widgets/SlideTransition/
- FadeTransition: http://laomengit.com/flutter/widgets/FadeTransition/
- AnimatedModalBarrier: http://laomengit.com/flutter/widgets/AnimatedModalBarrier/
- AnimatedList: http://laomengit.com/flutter/widgets/AnimatedList/
- Hero: http://laomengit.com/flutter/widgets/Hero/
其實動畫不僅僅是這些控件屬性變化,還有使用Paint自繪制的動畫。
看到這麼多元件是不是暈了,我也沒想到會有這麼多元件,那我們改如何選擇适合的元件?這真是一個靈魂拷問啊。
這是《Flutter 動畫系列》的第一篇,接下來還有:
- 組合動畫
- 自定義動畫
- 到底如何選擇動畫控件
交流
如果你對Flutter還有疑問或者技術方面的疑惑,歡迎加入Flutter交流群(微信:laomengit)。
同時也歡迎關注我的Flutter公衆号【老孟程式員】,公衆号首發Flutter的相關内容。
Flutter位址:
http://laomengit.com裡面包含160多個元件的詳細用法。