Start Code
@override
Widget build(BuildContext context) {
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) 可以放大范围,从左上角,放大到全屏。
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, 变化的三个属性,求出变化后的值。
-
我们可以将动画理解为变化的特例,流畅的变化,即为动画.
关联核心代码
void resync(TickerProvider vsync) {
final Ticker oldTicker = _ticker!;
_ticker = vsync.createTicker(_tick);
_ticker!.absorbTicker(oldTicker);
}
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();
}
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;
}