fluro 轉場動畫源碼
在使用自定義轉場動畫前,先扒一扒 fluro 的源碼,通過源碼可以發現這麼一個標準的轉場方法:
RouteTransitionsBuilder _standardTransitionsBuilder(
TransitionType? transitionType) {
return (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
if (transitionType == TransitionType.fadeIn) {
return FadeTransition(opacity: animation, child: child);
} else {
const Offset topLeft = const Offset(0.0, 0.0);
const Offset topRight = const Offset(1.0, 0.0);
const Offset bottomLeft = const Offset(0.0, 1.0);
Offset startOffset = bottomLeft;
Offset endOffset = topLeft;
if (transitionType == TransitionType.inFromLeft) {
startOffset = const Offset(-1.0, 0.0);
endOffset = topLeft;
} else if (transitionType == TransitionType.inFromRight) {
startOffset = topRight;
endOffset = topLeft;
} else if (transitionType == TransitionType.inFromBottom) {
startOffset = bottomLeft;
endOffset = topLeft;
} else if (transitionType == TransitionType.inFromTop) {
startOffset = Offset(0.0, -1.0);
endOffset = topLeft;
}
return SlideTransition(
position: Tween<Offset>(
begin: startOffset,
end: endOffset,
).animate(animation),
child: child,
);
}
};
}
從源碼可以看出,根據不同枚舉返回了不同的動畫(即 transitionBuilder
),其中TransitionType.fadeIn
使用的是Flutter 自帶的 FadeTransition
,通過改變透明度來完成動畫。而其他的左滑入、右滑入、下滑入和上滑入都是從初始偏移位置滑動到結束位置,使用的是 SlideTransition
。Flutter 除了上述的 FadeTransition
、SlideTransition
之外,還有如下的常用轉場形式:
-
RotationTransition
:旋轉轉場 -
ScaleTransition
:縮放轉場
既然是這樣,我們可以依葫蘆畫瓢,先用系統其他的轉場效果做一個自定義的轉場看看。
旋轉轉場動畫
先來看看旋轉的轉場RotationTransition,RotationTransition 的構造方法定義如下:
const RotationTransition({
Key? key,
required Animation<double> turns,
this.alignment = Alignment.center,
this.child,
}) : assert(turns != null),
super(key: key, listenable: turns);
其中 turns
是動畫控制,表示旋轉的弧度數,等於動畫控制值乘以2π。alignment
表示旋轉圍繞的中心位置,默認是居中的。旋轉的弧度不要太大,否則動畫過快,導致不太好看,經過驗證,推薦的起始值0.2至0.3之間,結束值爲0表示回到正常位置。起始值如果爲負,則是順時針;如果爲正則是逆時針,示例代碼如下:
//逆時針圍繞中心旋轉
RouterManager.router.navigateTo(
context,
RouterManager.transitionPath,
transition: TransitionType.custom,
transitionBuilder:
(context, animation, secondaryAnimation, child) {
return RotationTransition(
turns: Tween<double>(
begin: 0.25,
end: 0.0,
).animate(animation),
child: child,
);
},
);
//...
//順時針圍繞左下角旋轉
RouterManager.router.navigateTo(
context,
RouterManager.transitionPath,
transition: TransitionType.custom,
transitionBuilder:
(context, animation, secondaryAnimation, child) {
return RotationTransition(
alignment: Alignment.bottomLeft,
turns: Tween<double>(
begin: -0.25,
end: 0.0,
).animate(animation),
child: child,
);
},
);
其中 Tween
是系統自帶的線性插值方法。
縮放轉場動畫
縮放轉場這類在圖片預覽會比較常見,一般是從較小的比例縮放到1:1比例。使用方式和旋轉轉場類似,示例代碼如下:
RouterManager.router.navigateTo(
context,
RouterManager.transitionPath,
transition: TransitionType.custom,
transitionBuilder:
(context, animation, secondaryAnimation, child) {
return ScaleTransition(
scale: Tween<double>(
begin: 0.5,
end: 1.0,
).animate(animation),
child: child,
);
},
);
自定義轉場動畫
通過閱讀源碼,其實可以發現RotationTransition
、ScaleTransition
都是繼承自 AnimatedWidget
,因此我們可以自己寫一個自定義的 Transition
繼承自 AnimatedWidget
,在 build
方法中返回一個 Transform
對象即可。通過這種方式可以做自定義的轉場動畫效果。我們以變形爲例,可以利用 Matrix4
的 skew
方法,在 x 和 y 軸進行變形,就可以得到轉場類似卡片變形的效果。也可以只在 X 軸或 Y 軸變形(skewX
和 skewY
方法)。這裏以 x,y 軸同時變形定義了一個轉場動畫:
class SkewTransition extends AnimatedWidget {
const SkewTransition({
Key key,
Animation<double> turns,
this.alignment = Alignment.center,
this.child,
}) : assert(turns != null),
super(key: key, listenable: turns);
Animation<double> get turns => listenable as Animation<double>;
final Alignment alignment;
final Widget child;
@override
Widget build(BuildContext context) {
final double turnsValue = turns.value;
final Matrix4 transform =
Matrix4.skew(turnsValue * pi * 2.0, turnsValue * pi * 2.0);
return Transform(
transform: transform,
alignment: alignment,
child: child,
);
}
}
使用方式和 RotationTransition
類似:
RouterManager.router.navigateTo(
context,
RouterManager.transitionPath,
transition: TransitionType.custom,
transitionBuilder:
(context, animation, secondaryAnimation, child) {
return SkewTransition(
turns: Tween<double>(
begin: -0.05,
end: 0.0,
).animate(animation),
child: child,
);
},
);
實際也可以嘗試使用圍繞 X 軸旋轉,圍繞 Y 軸旋轉,以及變更中心點位置(alignment
)來實現不同的動畫轉場效果。如果需要更爲複雜的動畫效果,則可以研究動畫的實現,後續篇章將有對應動畫的介紹。
運行效果
運行效果如下圖所示:
總結
本篇介紹了 fluro 導航到其他頁面的自定義轉場動畫實現,Flutter本身提供了不少預定義的轉場動畫,可以通過 transitionBuilder
參數設計多種多樣的轉場動畫,也可以通過自定義的 AnimatedWidget
實現個性化的轉場動畫效果。