Staggered Animations
Staggered Animations就是交錯動畫,也可以稱之爲組合動畫。在實際的動畫使用過程中,動畫可能並不是由一個單一方式呈現的。漸變,位移,縮放等都是基礎的動畫,而我們有時候需要把這些基礎的動畫組合起來,使其成爲一個組合動畫,即交錯動畫。(下圖爲本文最終實現效果)
在Android開發中,是通過AnimationController來實現這種交錯動畫的。在Flutter開發中,也沿用了名爲AnimationController的類來實現。
組合動畫的代碼實現
對於如何在Flutter開發中,寫交錯動畫,我們可以通過AnimationController把動畫組合在一起,然後分別設置其動畫的參數即可。
對於AnimationController來說,控制器的值Tween必須屬於(0.0,1.0)。也就是說,組合動畫的所有間隔必須在0到1的數字之間進行,有了這個思路,我們來實踐實現其交錯動畫(組合動畫),代碼如下:
import 'package:flutter/scheduler.dart' show timeDilation;
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin{
AnimationController controller;
@override
void initState() {
// TODO: implement initState
super.initState();
controller=AnimationController(duration: const Duration(milliseconds: 2000),vsync: this);//初始化,動畫控制器,每個動畫都是執行2秒
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
controller.dispose();//銷燬釋放
}
Future<void> _playAnimation() async{
try{
await controller.forward().orCancel;//開始
await controller.reverse().orCancel;//反向
}on TickerCanceled{
}
}
@override
Widget build(BuildContext context) {
timeDilation=10.0;
return Scaffold(
appBar: AppBar(
title: Text("組合動畫"),
),
body: GestureDetector(
behavior: HitTestBehavior.opaque,//自己處理事件
onTap: (){
_playAnimation();
},
child: Center(
child: Container(
width: 300.0,
height: 300.0,
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.1),
border: Border.all(
color: Colors.black.withOpacity(0.5),
),
),
child: StaggedAnimation(controller: controller.view,),
),
),
),
);
}
}
class StaggedAnimation extends StatelessWidget{
//Curves.ease一種三次動畫曲線,速度快,結束慢
final Animation<double> controller;
final Animation<double> bezier;//透明度漸變
final Animation<double> width;//寬度變化
final Animation<double> height;//高度變化
final Animation<EdgeInsets> drift;//位移變化
final Animation<BorderRadius> borderRadius;//圓角變化
final Animation<Color> color;//顏色變化
StaggedAnimation({Key key,this.controller}):
bezier=Tween<double>(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(0.0, 0.1,curve: Curves.ease),
)
),
width=Tween<double>(
begin: 50.0,
end: 150.0,
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(0.125,0.250,curve: Curves.ease),
)
),
height=Tween<double>(
begin: 50.0,
end: 150.0,
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(0.250,0.375,curve: Curves.ease),
),
),
drift=EdgeInsetsTween(
begin: const EdgeInsets.only(bottom: 16.0),
end: const EdgeInsets.only(bottom: 75.0),
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(0.375,0.5,curve: Curves.ease),
),
),
borderRadius=BorderRadiusTween(
begin: BorderRadius.circular(4.0),
end: BorderRadius.circular(75.0),
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(0.5,0.75,curve: Curves.ease),
),
),
color=ColorTween(
begin: Colors.indigo[100],
end: Colors.orange[400],
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(0.75,1.0,curve: Curves.ease),
),
),
super(key:key);
Widget _buildAnimation(BuildContext context,Widget child){
return Container(
padding: drift.value,
alignment: Alignment.bottomCenter,
child: Opacity(//透明組件
opacity: bezier.value,
child: Container(
width: width.value,
height: height.value,
decoration: BoxDecoration(
color: color.value,
border: Border.all(
color: Colors.indigo[300],
width: 3.0
),
borderRadius: borderRadius.value,
),
),
),
);
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
builder: _buildAnimation,
animation: controller,
);
}
}
上面代碼使用的是AnimatedBuilder,這樣可以不用去顯式的去添加addlistener,節省很多代碼,不懂的可以回顧前面的內容,其他的代碼不用多說,還有,dart異步在第三篇dart語言中有講到,這裏就不過多的贅述了,這段組合動畫實現的效果如首圖所示。