X

flutter 动画

2022/3/31

flutter有很多动画实现方式 我尝试的是其中比较常规的

即通过继承AnimatedWidget实现动画 至于画什么 就画博客首页里的那只鸟吧

class Bird extends AnimatedWidget {
  const Bird({Key? key, required AnimationController controller})
      : super(key: key, listenable: controller);

  Animation<double> get _progress => listenable as Animation<double>;

AnimatedWidget的动画实现原理比较简单,通过传入 controller 然后用get方法拿到插值。 而controller 则需要一个实现了TickerProvider的类来提供。

class _AniBirdState extends State<AniBird> with TickerProviderStateMixin {
  late final AnimationController _controller =
      AnimationController(vsync: this, duration: const Duration(seconds: 3))
        ..repeat(reverse: true);

  @override
  Widget build(BuildContext context) {
    return Bird(controller: _controller);
  }
}

这里之所以要继承State是因为TickerProvider接口必须是StateWidget才行,

而你用到了StateWidget 那必然只能通过StatefulWidget来实现了。

剩下的就是烦琐的拼装,相对于web的css来说,写起来还是挺费功夫。 Screenshot 2022-03-31 222851.png

对于各个组件的动画,你可能需要不同的速度和曲线的插值,理论上一个基础插值是可以通过方法变换速率曲线和延迟反复等等,其实就是函数图像的各种改变。从而能够用一个controller实现不同部位的动画控制。

这里举个栗子,速率改变:

double boosts(double origin, double rate) {
  var n = (origin * rate).ceil() % 2 == 1;
  var b = origin * rate % 1;
  return n ? 1 - b : b;
}

然后在Bird中你就可以如下改变动画速度:

      double v = _progress.value;
      double v1 = boosts(v, 10);
      double v2 = boosts(v, 2);
      Widget foot = Transform(
        transform: Matrix4.rotationZ(-0.3 - v2 * 0.6),
        origin: Offset(d * 0.075, 0),
        child: BirdFoot(
          height: d * 0.5,
        ),
      );
最终效果如下: Animation.gif

这样写下来,感觉缺憾还是有的,我觉得自己需要一个更为清晰专注的动画表现方式,即如如何更加精准分离动画的配置。

Commit