動畫運行的原理 任何程式的動畫原理都是一樣的,即:視覺暫留,視覺暫留又叫視覺暫停,人眼在觀察景物時,光信號傳入大腦神經,需經過一段短暫的時間,光的作用結束後,視覺形象並不立即消失,這種殘留的視覺稱“後像”,視覺的這一現象則被稱為“視覺暫留”。 電影就是依靠視覺暫留,在感官上電影是連續的。使動畫有流暢 ...
動畫運行的原理
任何程式的動畫原理都是一樣的,即:視覺暫留,視覺暫留又叫視覺暫停,人眼在觀察景物時,光信號傳入大腦神經,需經過一段短暫的時間,光的作用結束後,視覺形象並不立即消失,這種殘留的視覺稱“後像”,視覺的這一現象則被稱為“視覺暫留”。
電影就是依靠視覺暫留,在感官上電影是連續的。使動畫有流暢的感覺,幀率至少要達到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
和upperBound
不能在直接設置為100和300,因為AnimationController需要被CurvedAnimation使用,值的範圍必須是0-1。 - 由於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多個組件的詳細用法。