专栏首页编程之路的专栏Flutter 动画看这篇彻底学通

Flutter 动画看这篇彻底学通

动画

理解原理

人眼在观察景物时,光信号传入大脑神经,需经过一段短暂的时间,光的作用结束后,视觉形象并不立即消失,这种残留的视觉称“后像”,视觉的这一现象则被称为“视觉暂留”,又称“余晖效应”。

静态的画面之所以能够运动,正是基于这一原理。具体应用则是电影放映,动画片播放等场景。

每张画面帧的快速切换

相关概念

帧是影像动画中单幅画面,一帧就是一幅静止的画面。例如电影胶片中的每一格即为一帧。

FPS

FPS(Frame Per Second)指每秒显示的帧数。例如电影每秒播放24帧,即帧率为24FPS。帧率越大显示的画面越流畅。

刷新频率

通常指显示器的刷新频率,市面上的显示器刷新频率主要为60Hz或120Hz。这里60Hz表示屏幕一秒钟可以刷新60张画面。

FPS帧率是由GPU决定,刷新频率是由显示器决定,显示器的刷新频率在物理上约束了帧数的表现上限。

Flutter 动画

详见Flutter官方文档 Flutter中的动画[1]

Flutter中的动画可以分为两种类型

  • 补间动画(Tween Animation)
  • 基于物理的动画(Physics-based animation)

基于物理的动画是一种遵循物理学定律的动画形式。例如弹簧、阻尼效果等等

三种动画模式

  • 列表或网格动画(Animated list or grid)。指item的添加或删除操作,见`AnimatedList`[2] 示例
  • 共享元素转换(Shared element transition)。实现路由(页面)之间的共享元素过渡动画,通常称为Hero动画
  • 交错动画(Staggered animation)。动画被分解为较小的动作,它们可以是连续的,或者可以部分或完全重叠。

插值器

主要描述值的变化规律(匀速、加速),决定变化的趋势,能更细腻的表达运动的物理特性。插值器通常是一个数学函数。简单说,插值器就是根据时间流失的百分比 计算当前属性改变的百分比

估值器

插值器描述了变化规律,接下来则需要交给估值器计算出具体的数值。因此估值器的主要作用就是协助插值器实现非线性运动的动画。

简单说,估值器就是根据当前属性改变的百分比来计算改变后的属性值

总结,插值器决定属性值随时间变化的规律;而具体变化属性数值则交给估值器去计算

相关对象

Ticker

可以被应用在 Flutter 的每个对象中,当对象实现了 Ticker 的功能后,每次动画帧改变便会通知该对象。Flutter 提供了 TickerProvider 类型,但它是一个抽象类,它有两个具体子类可快速实现该功能,SingleTickerProviderStateMixinTickerProviderStateMixin。前者只适用包含单个AnimationController的情况,如果你有多个AnimationController,则应使用后者。

用法:如在有状态控件下使用动画时,通常在 State 对象下混入 TickerProviderStateMixin

AnimationController

即动画控制器。用来控制动画,如动画的启动、暂停等。它接受两个参数,第一个是 vsync,必须是一个 Ticker 对象,其作用是当接受到来自 tweens 和 curves 的新值后通知对应对象,第二个参数是 duration, 为动画持续的时长。

要创建一个动画,首先要创建一个AnimationController。一旦创建了它,你就可以开始基于它构建其他动画。

常用方法:

  • forward() 从头向尾正向启动动画
  • reverse() 从尾到头逆向执行动画
  • fling() 使用阻尼效果驱动动画
  • repeat()正向运行此动画,并在完成后重复执行此过程
  • reset() 将控制器的值重置为开始值(如果正在进行则停止动画)
  • stop() 停止运行动画
  • dispose() 释放资源

Animation

是Flutter动画库中的一个核心类,也是一个抽象类,表示一个特定类型的值。其实它封装了动画过程中的值和状态。大多数执行动画的widgets都会收到一个Animation类型对象作为参数,它们从这个对象中读取动画的当前值,并监听该值的变化。

简单说,它生成指导动画的值,知道动画的当前状态(例如,它是开始、停止还是向前或向后移动),但它不知道屏幕上显示的内容。

主要是四种状态类型

  • AnimationStatus.forward 动画从头到尾执行
  • AnimationStatus.reverse 动画从尾到头执行
  • AnimationStatus.completed 动画已执行完成。注意,此状态指动画在终点停止
  • AnimationStatus.dismissed 动画处于停止状态。注意,此状态指动画回到起始点停止,即调用了reverse()方法

它的具体实现类:

  • `AlwaysStoppedAnimation`[3] 始终以给定值停止的动画。该状态始终为AnimationStatus.forward
  • `CompoundAnimation`[4] 一个用于组合多个动画的接口。子类只需要实现取值器来控制子动画的组合方式。可以链式组合2个以上的动画
  • `CurvedAnimation`[5] 将曲线应用于另一个动画的动画。当你想对动画对象应用非线性曲线时,它很有用
  • `ProxyAnimation`[6] 作为另一个动画的代理的动画
  • `ReverseAnimation`[7] 与另一个动画相反的动画(反向动画)
  • `TrainHoppingAnimation`[8] 接收两个父类,并在它们的值交叉时在它们之间切换
  • `AnimationController`[9] 动画的控制器

需要注意,AnimationController 也是它的一个实现类。大多数 Animation 子类都采用明确的 “父级提供的” Animation<double>。可以说它们是由父级驱动的。

CurvedAnimation 子类接收一个 Animation<double>类(父级)和几个 Curve 类(正向和反向曲线)作为输入,并使用父级的值作为输入提供给曲线来确定它的输出。CurvedAnimation 是不可变和无状态的。

ReverseAnimation 子类接收一个 Animation<double> 类作为它的父级,但反转动画所有的值。父级动画的状态和方向也会被反转。ReverseAnimation 是不可变和无状态的。

ProxyAnimation 子类接收一个 Animation<double> 类作为其父级,并仅转发该父级的当前状态。然而,父级是可变的。

Tween

继承自Animatable,实际上它是一个补间值生成器。相当于在一个固定的时间内,生成一系列从begin到end的数值。对应到前面所述的概念,可以将之理解为一个线性的估值器

默认情况下,Flutter 中的动画将任何给定时刻的值映射到介于 0.0 和 1.0 之间的 double 值。

Flutter 框架也为我们封装了许多用于具体属性动画的Tween类实现:

  • AlignmentGeometryTween[10]
  • AlignmentTween[11]
  • BorderRadiusTween[12]
  • BorderTween[13]
  • BoxConstraintsTween[14]
  • ColorTween[15]
  • ConstantTween[16]
  • DecorationTween[17]
  • EdgeInsetsGeometryTween[18]
  • EdgeInsetsTween[19]
  • FractionalOffsetTween[20]
  • IntTween[21]
  • MaterialPointArcTween[22]
  • Matrix4Tween[23]
  • RectTween[24]
  • RelativeRectTween[25]
  • ReverseTween[26]
  • ShapeBorderTween[27]
  • SizeTween[28]
  • StepTween[29]
  • TextStyleTween[30]
  • ThemeDataTween[31]

Curve(动画曲线)

用来调整动画过程中随时间的变化率,默认情况下,动画以均匀的线性模型变化。我们可以通过继承 Curve 类来定义动画的变化率,比如创建加速、减速或者先加速后减速等曲线模型。可以将之理解为一个插值器

Flutter 内部也提供了一系列实现相应变化率的 Curves 对象,见文档Curves 文档[32]

同时,我们还可以通过继承Curve类重写transform方法来自定义自己的非线性插值器。

class MyCurve extends Curve{

  @override
  double transform(double t) {
    return math.sin(t * math.PI * 2);
  }
}

动画流程

总的来说,Flutter中的动画系统基于`Animation`[33]对象,widget应该在build函数中读取Animation对象的当前值, 并且可以监听动画的状态改变。代码中我们使用AnimationController管理Animation,并设置监听。

本文分享自微信公众号 - 编程之路从0到1(artofprogram),作者:编程之路从0到1

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-10-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • (译)SDL编程入门(14)动画精灵和VSync

    动画简而言之就是展示一个又一个的图像来制造运动的假象。在这里我们将展示不同的精灵来制作一个简笔画的动画。

    arcticfox
  • Python小白的数据库入门

    sqlite3 以上两个是主流的关系型数据库,我们观察之后发现,它们与我们熟知的Excel好像也没有什么不同。关系型数据库里面放的都是一张张的表,就如同Exce...

    arcticfox
  • 程序员C语言快速上手——基础篇(二)

    在代码目录下打开cmd命令行或打开VSCode中的命令行,VS Code快捷键是【Ctrl】+【~】

    arcticfox
  • iOS学习——核心动画

      Core Animation(核心动画)是一组功能强大、效果华丽的动画API,无论在iOS系统或者在你开发的App中,都有大量应用。核心动画所在的位置如下图...

    mukekeheart
  • 【iOS开发】iOS 动画详解

    在移动开发中,为了提高用户体验,会用到一些动画来提高应用的视觉效果。让人有眼前一亮的感觉。同时有动画的过渡过程,会让应用看起来不是那么的生硬,更吸引用户。

    吴老师
  • 前端基础-jQuery动画效果

    cwl_java
  • [Android技术专题]动画那点小秘密

    在Android应用开发中我们每天都在接触动画(Activity开、关,页面滑动、点击按钮等都有动画效果),但入门容易,真正做好很难。如果要把效果做得自然、看...

    open
  • Web高性能动画及渲染原理(1)CSS动画和JS动画

    Web动画的本质是元素状态改变造成的样式变更,CSS动画和JS动画的区别并不是由语言来决定的,而是由两者的特点和适用场景来判断的。CSS动画简洁高效,提升交互体...

    大史不说话
  • Flutter动画【1】

    在前面的文章中我们花了很多的时间去讲了Flutter中的Widget以及用户操作,但是我们却很少去关注与用户的交互效果,当然这并不会导致我们的程序崩溃或者不能实...

    flyou
  • 中国第五届CSS大会分享:CSS TIME

    懵懂少年有幸受邀参加3.30中国第五届CSS大会分享,感谢业界大咖的不嫌弃,鉴于CSS的更新频率不及JS各种迭代高,新的特性组织起来对于分享的主题会比较散,所以...

    腾讯技术工程官方号

扫码关注云+社区

领取腾讯云代金券