2

图片描述

本例的代码参考这里

并行动画

当多个动画定义同时指向某个组件,并使用动画控制器启动时,就产生了并行动画(Parallel Animation)。例如我们可以让一个组件:

  • 移动的同时改变大小
  • 旋转的同时边界颜色闪烁
  • 圆形图片模糊的同时形状越来越方

总之,掌握了动画原理以后我们知道,只要能将一个动画抽象值与一个组件的某个外观属性值联系起来,那么就能在动画中展现出连续平滑的外观变化。这一点,任何平台(Web、Android)的原理都是一致的。

例子

接前一篇的例子,我们让一个移动的正方形在位移过程中逐渐变为圆形。

在已有的animation基础上,再添加一个新的animation用以控制动画组件的边角半径。

class ParallelDemoState extends State<ParallelDemo> with SingleTickerProviderStateMixin {
    ...
    Tween<double> slideTween = Tween(begin: 0.0, end: 200.0);
    Tween<double> borderTween = Tween(begin: 0.0, end: 40.0);  // 添加边角半径变动范围
    Animation<double> slideAnimation;
    Animation<double> borderAnimation; // 添加边角半径动画定义
    
    @override
    void initState() {
        ...
        controller = AnimationController(duration: Duration(milliseconds: 2000), vsync: this);
        slideAnimation = slideTween.animate(CurvedAnimation(parent: controller, curve: Curves.linear));
        borderAnimation = borderTween.animate(CurvedAnimation(parent: controller, curve: Curves.linear)); // 定义边角半径动画
    }
    
    ...
        
    @override
    Widget build(BuildContext context) {
        return Container(
            width: 200,
            alignment: Alignment.centerLeft,
            child: Container(
                margin: EdgeInsets.only(left: slideAnimation.value),
                decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(borderAnimation.value), // 边角半径的属性上添加动画
                    color: Colors.blue,
                ),
                width: 80,
                height: 80,
            ),
        );
    }
}

串行动画

串行动画(Sequential Animation)顾名思义,多个动画像肉串一样一个接一个的发生。但这只是从现象上观察出的结果,实际的运行方式和并行动画差别不大。串行动画的关键之处在于,它为每个动画的发生设定了一个计时器,只有到特定时间点时,特定的动画效果才会发生。

例如设计一个3秒钟的动画:

  • 移动动画从0秒开始,持续1秒
  • 旋转动画从1秒开始,持续1.5秒
  • 缩放动画从2秒开始,持续0.7秒

那么,最后的动画效果便是:

  1. 0~1秒,动画元素在移动
  2. 1~2秒,动画元素在旋转
  3. 2~2.5秒,动画既在旋转又在缩放
  4. 2.5~2.7秒,动画在缩放
  5. 2.7~3秒,动画静止不动

例子

在串行动画例子的基础上,我们加上计时器Interval的处理。Interval有三个参数,前两个参数指示了动画的开始和结束时间。这两个参数都是以动画控制器的Duration时长的比例来计算的。例如:

  • Slide动画分别为0.0和0.5,表示动画从0秒(2000ms 0.0)这个时间点开始,至1秒(2000ms 0.5)这个时间点结束
  • Border动画分别为0.5和1.0,表示动画从1秒(2000ms 0.5)这个时间点开始,至2秒(2000ms 1.0)这个时间点结束
class SequentialDemoState extends State<ParallelDemo> with SingleTickerProviderStateMixin {
    ...
    
    @override
    void initState() {
        ...
        controller = AnimationController(duration: Duration(milliseconds: 2000), vsync: this);
        // slideAnimation = slideTween.animate(CurvedAnimation(parent: controller, curve: Curves.linear));
        // borderAnimation = borderTween.animate(CurvedAnimation(parent: controller, curve: Curves.linear)); // 定义边角半径动画
        
        // 换一种写法,加入Interval
        slideAnimation = slideTween.animate(CurveTween(curve: Interval(0.0, 0.5, curve: Curves.linear)).animate(controller));
        borderAnimation = borderTween.animate(CurveTween(curve: Interval(0.5, 1.0, curve: Curves.linear)).animate(controller));
    }
    
    ...
        
    @override
    Widget build(BuildContext context) {
        return Container(
            width: 200,
            alignment: Alignment.centerLeft,
            child: Container(
                margin: EdgeInsets.only(left: slideAnimation.value),
                decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(borderAnimation.value), // 边角半径的属性上添加动画
                    color: Colors.blue,
                ),
                width: 80,
                height: 80,
            ),
        );
    }
}

一光年
158 声望3 粉丝