前段時間學習Flutter動畫時接觸了Transform類,查找官方文檔時無心間看到了時鐘翻頁動畫以爲也挺好玩的,因此就本身動手使用動畫和Transform來實現翻頁特效。html
開始前本身也思考過若是實現翻頁動畫,但實際操做時卻發現思路不太正確最後只好做罷。最後仍是參考了已有翻頁實現方式瞭解實現原理,其實方法很簡單經過Transform對數字上部分進行矩陣變化操做實現頁面翻轉效果。下面經過圖解方式更好解釋實現過程。git
下圖所展現內容是從橫切面看到的效果。正常狀況下是從示例圖左邊到右邊的查看視角👉。github
![]() |
|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
ClipRect(
child: Align(
alignment: _alignment,
heightFactor: 0.5,
child: Container(
alignment: Alignment.center,
width: 100,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
child: Text(
"$_value",
style: TextStyle(
fontSize: 80,
color: Colors.white,
fontWeight: FontWeight.w700,
),
),
),
),
)
複製代碼
Column(
mainAxisSize: MainAxisSize.min,
children: [
Stack(
children: <Widget>[
//下一個數字的上部分
ClipRectText(_stateNum + 1, Alignment.topCenter),
//當前數字的上部分,當_isReversePhase爲true時和平面呈90度角至關於隱藏
Transform(
transform: Matrix4.identity()
..setEntry(3, 2, 0.006)
..rotateX(_isReversePhase ? pi / 2 : _animation.value),
alignment: Alignment.bottomCenter,
child: ClipRectText(_stateNum, Alignment.topCenter)),
],
),
Padding(
padding: EdgeInsets.only(top: 2.0),
),
Stack(
children: <Widget>[
//當前數字的下部分
ClipRectText(_stateNum, Alignment.bottomCenter),
//下個數字的下部分,當_isReversePhase爲true時才執行翻轉動畫不然一直和平面呈90度
Transform(
transform: Matrix4.identity()
..setEntry(3, 2, 0.006)
..rotateX(_isReversePhase ? -_animation.value : pi / 2),
alignment: Alignment.topCenter,
child: ClipRectText(_stateNum + 1, Alignment.bottomCenter)),
],
)
],
)
複製代碼
_controller = new AnimationController(
duration: Duration(milliseconds: 450), vsync: this)
..addStatusListener((status) {
//動畫正向執行,正向執行結束後進行反向執行
if (status == AnimationStatus.completed) {
_controller.reverse();
_isReversePhase = true;
}
//動畫反向執行,反向執行結束後一次動畫翻轉週期結束。當前數字更新到最新的
if (status == AnimationStatus.dismissed) {
_isReversePhase = false;
_stateNum += 1;
}
})
..addListener(() {
setState(() {});
});
//動畫數值使用0度角到90度角
_animation = Tween(begin: _zeroAngle, end: pi / 2).animate(_controller);
複製代碼
@override
void didUpdateWidget(FlipNumText oldWidget) {
//當組件的數字num發生改變時執行動畫控制器
if (this.widget.num != oldWidget.num) {
_controller.forward();
_stateNum = oldWidget.num;
}
super.didUpdateWidget(oldWidget);
}
複製代碼
翻頁動畫效果實現中不少運用到了數學算法。如Pi角度、Transform的2D、3D變換、Matrix矩陣使用等都離不開數學計算。目前對於Matrix還只停留在使用上,後續須要深刻理解其原理才能更好的運用。同時也但願有小夥伴一塊兒交流共同進步😸😊。api