前段时间学习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