敞开成长之旅!这是我参加「日新方案 12 月更文应战」的第9天,点击检查活动详情

从上一次给咱们介绍了自定义单组件布局之后,一向都想写一个关于运用单组件自定义动画的文章. 不过,因为一向没有好的体裁,暂时搁置了.今天和目标谈天的时分偶然发现一个很有意思的动画准备完成一下

原因

这次想做的动画是和目标谈天的时分.对方发的一个表情

Flutter 动画集锦之小企鹅跑啊跑

信任这个表情很多人应该在wx中也发过, 小企鹅跑来跑去的十分有意思.今天咱们就经过 CustomSingleChildLayout 来完成这个动画.

剖析

首要咱们先剖析一下这张图的一个构成.简单来说,便是一个 不规则的图形在来回上下的左右反复运动. 更深化来看, 小企鹅在 移动过程中手的方向也会随移动方向发生改动 . 但是仔细看, 你会发现, 这实际上是x轴回转的一个镜像.

Flutter 动画集锦之小企鹅跑啊跑

知道这些基本点后, 咱们就能够开始规划咱们的动画了~

Coding

准备

  • 一张通明图片
    ps: 这次演示运用的是一张360*360的图片
    Flutter 动画集锦之小企鹅跑啊跑
  • 前置教程
    假如你发现过程中感觉有些迷茫的话, 无妨静下心先阅读一下关于自定义布局的讲解部分. Flutter 玩转自定义布局之单组件布局

正篇

制作布景

首要, 咱们创立一个居中的100*200的黄色布景

Scaffold(
      body: Center(
        child: Container(
          color: Colors.yellow,
          height: 100,
          width: 200,
        ),
      ),
    );

制作小企鹅

在Container 内部创立一个CustomSingleChildLayout , 因为外部现已给了限制, 咱们这儿不需求额定经过_DemoSingleDelegate 的 getSize(BoxConstraints constraints) 去给外部束缚尺寸. 一起, 咱们创立一个Image 来加载需求的图片. 假如你有自己喜爱的图片, 也能够自行加载, 值得注意的是, 你也需求和本文相同运用一张正方形图片,否则需求依据图片大小自行适配下. 为了便利后边的核算. 咱们在 _DemoSingleDelegate 中, 重写getConstraintsForChild(BoxConstraints constraints) 的方法, 返回值为BoxConstraints.tight(Size(100, 100)) . 这样便能够将小企鹅束缚在100*100 的范围内.

    CustomSingleChildLayout(
        delegate: _DemoSingleDelegate(),
        child: Image.asset(
            'assets/images/qiuqiu.png',
            height: 100,
            width: 100,
        ),
    ),

效果

Flutter 动画集锦之小企鹅跑啊跑

小企鹅动起来

在小企鹅制作到方块中后, 咱们怎么让它动起来呢? 这儿需 凭借AnimationController, 它的作用主要是推动小企鹅运动. 咱们知道 AnimationController 有个repeat属性, 天然解决了小企鹅在运动中需求来回奔跑的问题.

    AnimationController controller =
        AnimationController(vsync: this, duration: const Duration(seconds: 1));
    /// 重复运动
    controller.repeat(reverse: true);

那么, 如何控制小企鹅的方位呢? 咱们能够经过 AnimationController 运用动画器Animation, Animattion能够自定义动画的取值和范围. 这儿咱们先创立一个Animation

/// 用来记录小企鹅的位移
class _DemoInfo {
  double x;
  double y;
  _DemoInfo(this.x, this.y);
}
class _DemoAnimation extends Animatable<_DemoInfo> {
  @override
  _DemoInfo transform(double t) {
    ...
  }
}

创立Animation 之后, 咱们发现它内部供给了一个 transform(double t) 的方法. 这儿的 t 即 AnimationController的value, 也便是当前动画执行的进展. 咱们依据进展来反推小企鹅的方位. 实际上小企鹅的方位很像函数中的正弦函数

Flutter 动画集锦之小企鹅跑啊跑
咱们假如按正常的正弦函数的话 实际上咱们只有上下移动一次. 正弦的公式是 y = A sin(Bx + C) + D. 周期的核算公式是 2/B . 也便是说咱们 B 越大, 一起间内,周期越短,上下移动的频次就越高. 咱们以 B 等于 6 为例:
Flutter 动画集锦之小企鹅跑啊跑
其中,蓝色为 B 等于 1 的时分,红色为 B 等于 6 的时分. 咱们一起间内能够上下移动 6 次, 了解到了这一点后. 咱们就能够依据 AnimationController的value 来核算小企鹅相应的方位了.

    // 因为小企鹅左右还有空白的部分,咱们实际核算中还要减去这部分.
    // 因而x轴要从-25开始核算, y轴咱们能够自定义初始的高度, 然后
    // 改动振幅,也便是公式中的A. 这样咱们上下偏移的间隔别离便是10.
    return _DemoInfo(-25 + 150.0 * t, 30 + 10 * sin(t * 6 * pi));

核算好小企鹅的方位后, 咱们就要同步自定义布局的_DemoSingleDelegate . 咱们把 Animation 传入_DemoSingleDelegate .

  Animation<_DemoInfo>? animation;
  _DemoSingleDelegate({required this.animation}) : super(relayout: animation);

这样当动画执行时, 咱们就能够同步更新画布了. 让咱们来看看小企鹅跑起来什么样吧!

Flutter 动画集锦之小企鹅跑啊跑

小企鹅转向

咱们发现在运动过程中,小企鹅并不会在走到头的时分转向. 回转的本质是对小企鹅的x轴回转, 咱们来完成一下.

    AnimatedBuilder(
        builder: (BuildContext context, Widget? child) {
            return Transform.scale(
                /// 这儿当动画forward运行时,小企鹅往左跑. 在reverse时, 小企鹅右跑
                scaleX:animation.status == AnimationStatus.forward ? 1 : -1,
                child: child,
            );
        },
        animation: animation,
        child: Image.asset(
            'assets/images/qiuqiu.png',
            height: 100,
            width: 100,
        ),
    ),

效果

Flutter 动画集锦之小企鹅跑啊跑

完善界面

小企鹅转向后, 咱们发现小企鹅的脚是超出色块的. 这个需求咱们手动裁切一下, 咱们在 CustomSingleChildLayout 外加上一个ClipRect 就能够啦!

Flutter 动画集锦之小企鹅跑啊跑

源码

github.com/weniner/flu…

结语

这儿是WeninerIo,酷爱生活且酷爱游览.假如你对这次的分享感兴趣又或者有什么疑惑, 无妨评论区留言 + 重视.期待下一次更好的相遇.