Code前端首页关于Code前端联系我们

Flutter实用动画开发:翻页效果

terry 2年前 (2023-09-23) 阅读数 69 #移动小程序

我在学习Flutter动画的时候就遇到过这样的课程。在寻找官方文档时,我偶然发现了钟面转动动画,觉得很好玩,所以我想知道如何使用动画和自己变换。了解翻页效果。 Flutter实战动画开发:翻页效果实现

想法

开始之前我也想过如何实现翻页动画,但是在实际活动过程中我发现这个想法不对,只好放弃。参考了现有的翻页实现方法,发现方法其实很简单。使用变换对数字的上半部分进行矩阵转换操作,达到翻页的效果。下面通过图片更好地解释了申请过程。

插图

下图显示了横截面的渲染。通常,示例图像中的视角是从左到右的。

Flutter实战动画开发:翻页效果实现
Flutter实战动画开发:翻页效果实现Flutter实战动画开发:翻页效果实现
Flutter实战动画开发:翻页效果实现Flutter实战动画开发:翻页效果实现
Flutter实战动画开发:翻页效果实现Flutter实战动画开发:翻页效果实现
  • STEP1
    首先,您可以使用 ClipRect 组件将数字分成两部分。 A和D分别表示使用ClipRect将数字的上半部分和下半部分进行分割,并使用A和D在页面上显示下一个数字。 C和B表示当前准备翻转的数字。一开始我们看到它是一个由C和B组成的数字。
  • STEP2
    然后,为了实现C翻起来的动画效果,C使用变换进行变形:setEntry进行变形处理,rotateX对X轴进行旋转操作,旋转角度为90度。
  • STEP3
    当C旋转90度时,底部上部会慢慢出现一个数字。如果C旋转90度,原本垂直不可见的D也会相对X轴旋转90度。在这个过程中,之前的数字B的下部慢慢被覆盖。最后A、B、C、D同时改为下一次要显示的值,C、D重置到原来的位置,进行下一轮动画。

代码部分

  • 数字分割部分
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角、2D和3D变换的变换、使用矩阵矩阵等,都是数学计算不可或缺的部分。目前只使用Matrix。今后我们需要深入理解它的原理,才能更好地使用它。

作者:JulyYu

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门