Flutter 源码学习 pt.2,Animation

162 阅读3分钟

Start Code

  @override
  Widget build(BuildContext context) {
    // Scale the path values to match the -1.0 to 1.0 domain of the Alignment widget.
    final Offset position = widget.path.transform(animation.value) * 2.0 - const Offset(1.0, 1.0);
    return Align(
      alignment: Alignment(position.dx, position.dy),
      child: widget.child,
    );
  }
  • 在使用动画中,如何初始坐标在中心,widget.path.transform(animation.value) * 2.0 - const Offset(1.0, 1.0) 可以放大范围,从左上角,放大到全屏。
/// An animation that is always complete.
///
/// Using this constant involves less overhead than building an
/// [AnimationController] with an initial value of 1.0. This is useful when an
/// API expects an animation but you don't actually want to animate anything.
const Animation<double> kAlwaysCompleteAnimation = _AlwaysCompleteAnimation();
  • kAlwaysCompleteAnimation 是_AlwaysCompleteAnimation 静态具体实现,可以用在需要动画参数,但不需要提供动画的场景。Very Good.

Flutter 动画核心概念

  • Curve 曲线,给定时间插值t, 根据算法生成不同的值,是变化的核心
曲线含义
ParametricCurve定义抽象曲线,输入t, 返回范型
Curve一维,映射时间间隔到曲线值
SawTooth锯齿型
Threshold到达阈值,直接变化
Interval区间变化
Cubic二阶贝塞尔
ThreePointCubic三阶贝塞尔
Curve2D二维曲线,Offset
CatmullRomSpline生成平滑的曲线路径、模拟自然曲线和形状调整等任务
Curves默认实现合集
  • 动画,或者区间数值变化,定义一个值的区间,声明变化的边界
动画概要
AnimationStatus动画状态枚举
AnimationStatusListener动画状态回调
ValueListenableTransformer动画插值回调
Animation动画(数值区间)定义,定义动画相关操作
Animation.fromValueListenable从ValueListenable生成动画
ProxyAnimation一个动画是另一个动画的代理
ReverseAnimation反转动画
CurvedAnimation曲线动画,接受curve进行插值
TrainHoppingAnimation跳跃火车,两个动画间平滑过渡
CompoundAnimation组合动画抽象
AnimationMean组合动画具体实现
AnimationMax两个动画中的最大插值
AnimationMin两个动画中的最小插值
  • Tween 补间,是指给定start和end, 线性求中间态
名称概要
Animatable定义任何可被变化的类型
Tween补间动画抽象,继承Animatable
ColorTween颜色变化
SizeTween尺寸
RectTween矩形
IntTween整型
StepTween基于整型,阶梯状
ConstantTween恒定值,用于需要参数但无需变化
CurveTween替换默认线性插值为曲线
TweenSequence连续多个补间动画,可调权重
  • AnimationController 动画控制器,实现了Animation<double>,AnimationController责任是定义时间,我们知道动画即是变化,变化的三个属性,时间速率起止。观察变化是靠帧率,也就是触发变化,TickerProvider 就是承担这个责任,根据帧率触发AnimationController, 变化的三个属性,求出变化后的值。

  • 我们可以将动画理解为变化的特例,流畅的变化,即为动画.

关联核心代码

/// vsync 创建了一个ticker, 并提供了一个回调函数
/// Recreates the [Ticker] with the new [TickerProvider].
void resync(TickerProvider vsync) {
  final Ticker oldTicker = _ticker!;
  _ticker = vsync.createTicker(_tick);
  _ticker!.absorbTicker(oldTicker);
}
    
/// 根据ticker 的时间, 计算当前结果值
void _tick(Duration elapsed) {
    _lastElapsedDuration = elapsed;
    final double elapsedInSeconds = elapsed.inMicroseconds.toDouble() / Duration.microsecondsPerSecond;
    assert(elapsedInSeconds >= 0.0);
    _value = clampDouble(_simulation!.x(elapsedInSeconds), lowerBound, upperBound);
    if (_simulation!.isDone(elapsedInSeconds)) {
      _status = (_direction == _AnimationDirection.forward) ?
        AnimationStatus.completed :
        AnimationStatus.dismissed;
      stop(canceled: false);
    }
    notifyListeners();
    _checkStatusChanged();
    }

  /// forward 方法最终触发, Ticker的开始计时方法
  TickerFuture _startSimulation(Simulation simulation) {
    assert(!isAnimating);
    _simulation = simulation;
    _lastElapsedDuration = Duration.zero;
    _value = clampDouble(simulation.x(0.0), lowerBound, upperBound);
    final TickerFuture result = _ticker!.start();
    _status = (_direction == _AnimationDirection.forward) ?
      AnimationStatus.forward :
      AnimationStatus.reverse;
    _checkStatusChanged();
    return result;
  }