【Flutter学习】之动画实现原理浅析(一)

一,动画介绍

  动画对于App来说,非常的重要。很多App,正是因为有了动画,所以才会觉得炫酷。移动端的动画库有非常的多,例如iOS上的Pop、web端的animate.cssAndroid端的AndroidViewAnimations跨平台的Lottie等。正是因为有了这些封装好的动画库,我们制作酷炫的效果方便了不少。当然了,这些库都是基于各平台基础的动画API实现的,笔者今天要聊的,也就是基础的动画及背后的原理。

1.1 动画的本质

  动画顾名思义,就是动起来的画面。画面为什么会动起来了呢?在回答这个问题之前,我们先引入一个概念。

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

  视觉暂留被认为是电影的最重要的一个理论基础。我们看到的动画,实际上是一连串的画面组成,只不过是以很快的速度去播放,人眼在下一个画面出来之前,还残留着上一个画面的视觉,看起来就像是在没有间隔的播放这一系列的图片,也就是我们称之为的动画。

1.2 相关概念

  动画会有很多相关的概念,理解了这些概念,会对实际的使用更有帮助。

1.2.1 帧

  刚才在介绍动画本质的时候,用到了画面这个词汇,只是方便读者去理解,这个画面,在学术上叫做

帧就是影像动画中最小单位的单幅影像画面,一帧就是一副静止的画面。

 


 

  帧里面又分为关键帧过渡帧,这两概念是理解一些动画的基础,例如Android中的补间动画。在一些场景中,我们可能不会给出一个动画的所有帧,所以将帧分成关键帧过渡帧关键帧可以理解为一个动画的起始状态,而过渡帧则是系统自动完成插在关键帧之间的部分

 


 

  我们知道Android中的补间动画,基础的有四种类型,平移缩放旋转透明度。而我们设置动画的时候,通常只是设置起始的状态,也就是关键帧,中间过程其实我们并不需要去考虑,如果关注动画速率的话,顶多加一个差值器去控制,但是中间生成的帧我们并没有提供。

  系统为什么能够补齐过渡帧呢?我们看下这四种基本的动画类型,给定起始状态,中间状态我们其实是可以通过计算推演出来的,这也是系统为什么能够补齐的原因

  是不是只有这四种才可以通过系统填补过渡帧呢?显然不是的,例如一个跳跃前进的动画,添加一些限制条件,就可以推演出中间的状态。系统提供的只是比较常见的四种,并不是说只有这四种,而是绝大部分动画都可以通过这四种组合实现。当然了,肯定也是有实现不了的,这个时候有一个办法就是通过canvas画出来。

  另外再插一嘴,Android系统提供的四种动画操作,也是变换矩阵是四维的原因,具体的就不多说了,之前文章也有介绍过。

  最后一嘴,此处讲解帧的概念,拿了很多Android相关的知识去讲解,只是希望读者能够通过一些已知的概念,去理解一些未知的。动画的原理都一样,具体到某个平台,可能顶多就是实现或者叫法不一样罢了。

1.2.2 帧数与FPS

  小时候很多人都玩过书角动画。在书或者本子的一角,每一页都画上一个画面,然后拨书角,不同速度拨,动画的感受不一样,拨的越快,动画越流畅。这是为什么呢?这就牵扯到帧数与FPS了。

帧数,帧的数量。FPS(Frame per Second),即每秒显示帧数。

  这两个概念,主要是FPS有什么作用呢?这是因为人眼生理构造的原因。人眼残留镜像的时间是有限的,如果过了这个时间,下一帧还没有变化,就会感觉不流畅。但也不是帧数越大越好,毕竟人眼也是有极限的。

 


 

1.2.3 插值器

  如果动画播放一直都是这种匀速的进行,那表现形式就太单一了。那如何实现非线性的动画效果呢,这个时候就需要用到插值器了。

  插值器其实并不复杂,就是一个数学函数,设置属性值从初始值过渡到结束值的变化规律。每个平台都有自己定义好的一系列插值器,可以供开发者选择使用,也提供自定义的接口,本质上是一个贝塞尔函数。

  一个匀速插值器如下:

属性值百分比 = 时间百分比

1.3 如何实现

  动画的基本原理和一些基本概念都介绍了一下,现在来聊一下动画的实现。

  先抛开系统层级的各种渲染优化,也仅仅是以补间动画为例,假设以现有的移动平台基础上,去实现一套简单的动画框架,该如何去实现呢?

  以Android的为例,要实现平移、缩放、旋转、透明度这四种基础的补间动画,可以看到,这些都是基于某个属性的动画,平移是基于point、缩放是基于scale、旋转是基于angle、透明度是基于alpha。

  结合插值器,提炼出一个通用的动画类,这个类的作用是根据插值器,得到视图某个时间点的属性变化的状态。

  既然各个时间点的状态已经有了,剩下来的就是让各个状态渲染出来。底层的机制在此处不去讨论,这个地方就需要一个定时器,定时器的作用是每隔一段时间就把素材渲染到屏幕上。

  至此,一个简易的动画框架就出来了。如果对各平台比较了解的话,就知道我说的是视图动画,真正的动画引擎不是这么简单,涉及到的技术也比较复杂,但是大体的思想不会有错,不管是哪种动画,都是跟时间相关的帧序列,只是实现方式不同。

  这也是笔者为什么花这么多篇幅去介绍动画相关的概念,知道一些底层原理后,不管什么平台,怎么去实现,底层的思想肯定都差不多,只是实现上的不同。

二,其他平台的动画

  Flutter动画,与AndroidiOS等平台对比,其实本身并没有什么特别之处。基本的原理是一样的,只是提供的种类以及实现的方式不同罢了。

2.1 Android动画

  Android的动画,大的分类有两种:

  • 视图动画(View Animation)
  • 属性动画(Property Animation)

  视图动画又可以分为两类:

  • 补间动画(Tween Animation)
  • 逐帧动画(Frame Animation)

  这之间的差别是什么呢?它们只有实现上的差别

  • 补间动画是根据初始状态,系统自动补充中间状态
  • 逐帧动画则是需要我们提供每一帧
  • 视图动画只是作用于视图上,而不会改变控件的属性
  • 属性动画则是会实实在在的更改控件的属性

  可以看出Android的动画分类还是比较明晰的。

2.2 iOS动画

  iOS很久没弄了,在这里也简单说下,不对的话还请各位指正。

  • 隐式动画
  • 显式动画

  显式动画又可以分为两类:

  • 基础动画
  • 关键帧动画

  这些动画类别之间的差别是什么呢?

  • 隐式动画,顾名思义是不指定动画类型,更改某个属性,Core Animation来决定如何且何时去做动画;
  • 基础动画,根据起始值来做动画;
  • 关键帧动画,则是定义一系列关键帧,系统自动补齐中间的过渡帧。

  通过动画这一块儿,可以看出iOS的分类其实是比较的模糊的,有一些历史包袱。

2.3 css动画

  css动画大体上有两种:

  • Transition
  • Animation

  web中的动画分类简单的多了

  • Transition动画,给定起始值,可以结合插值器做动画;
  • Animation动画,则是定义一系列关键帧,系统补齐中间的过渡帧。

2.4 小节

  通过上面个平台动画粗略的介绍,动画在不同平台虽然被叫着不同的名称,本质上其实都差不多的,变来变去都是这几种方式,要么根据属性要么根据关键帧,要么更改绘制层,要么更改控件本身属性。一些游戏引擎,虽然我没有看,但是我觉得原理也大致相似。

三,Flutter动画

  上面铺垫了这么多,终于到Flutter动画了。Flutter是一门比较新的技术,历史包袱理应说是最小的。

3.1 Flutter动画分类

  Flutter动画分为两类:

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

  补间动画很好理解,基于物理的动画是这个什么鬼。

基于物理的动画是一种遵循物理学定律的动画形式

  举个例子,比方说你滑动一张图片,这个过程不是匀速的,而是起始速度快,然后慢慢的降速,就像一本书在地上往前推一样。它有什么特点呢?

  • 遵循物理学定律
  • 能够依据加速度和速度去计算和更新每一帧的动画数值
  • 当受力平衡时,动画为处于恒定运动或静止状态

  哈哈,最后一点是不是似曾相识,这样做的好处是什么呢?随着人们生活水平的极大提升,移动端硬件这些年也是赶英超美,人们不再满足于简单的动画,于是就有部分有(xian)识(de)之(dan)士(teng),实现了基于物理学定律的动画。

  这种动画iOS或者Android有没有呢,是有的,但不是作为最基础的动画API被提供。为什么其他平台没有将这个纳入最基本的动画中去呢?

  • 历史原因。iOS以及Android端多年前就诞生了,那个时候,硬件资源都是极其有限的,当时的环境不足以支撑这种动画效果。但也不是说没有,一些游戏引擎里面也是有的,但是作为操作系统,把这些集成进去,还是不太现实的。
  • 认知过程。电脑以及移动端这些年的发展,最开始只是满足于查看最简单的文本,然后各种图片视频。随着互联网的越来越普及,人们的需求越来越多了。于是,在一些游戏里面才会见到的基于物理学定律的动画,进入了寻常百姓家。反观一下,现在也是有非常多的“委屈”事物。例如人类几千年都是通过人眼看现实的事物,现在却被限制在一个小屏幕上,这其实是不合理的。所以AR、VR,还有一些动画片科幻片中的远程感知等技术,才会层出不穷,当然这个扯的有些远了。

  基于物理的动画这么好,那有什么好处呢?更自然,更加符合人们的认知。

3.2 分类的原因

  前面讲的各平台的动画,从本质上看,基于某个属性也好,帧动画也好,都是从一种状态到另一种状态,而中间过程是可以推演出来的,所以Flutter提供补间动画。

基于物理的动画,我猜测可能是为了实现其他平台上的一些效果,例如弹簧、阻尼效果等等。所以Flutter就提供了这种动画API,毕竟没什么包袱。

3.3 动画模式

  Flutter提炼了三种动画模式,与其说提炼出来的,倒不如说统一不能更为合适。

  • list、grid中的动画Animated list or grid)。场景是item的添加或者删除操作;
  • 转场动画Shared element transition)。场景是当前页面打开另一页面的过渡动画;
  • 交错动画Staggered animation)。场景是需要部分或者完全交错的动画。

3.4 复杂度

  Flutter的实现原理以及这个阶段,注定了做动画是非常麻烦的一件事情。跨平台的技术做动画都麻烦,这个似乎是通识,为了跨平台而同化的一些东西,到异化部分,就变得蛋疼了,动画正是这种存在。

  Flutter做动画复杂体现在哪些地方呢?

  • 实现的动画较少,这个是初期,没啥好说的;
  • 动画实现的方式复杂,这个是Flutter的设计思想所决定的。

四. 小节

  关于动画的具体的实现、一些底层的代码逻辑以及如何使用,将会在下一篇文章中做介绍。这篇文章更多的是偏于一些普适性的介绍,关于Flutter动画相关的介绍反而很少。希望读者能够了解一些动画的原理,以及各个平台动画的大致实现方式,这样可以更好的理解Flutter动画的设计思想。文中若有错误的地方,还恳请指出,在此不胜感激。

参考:
  1.https://juejin.im/post/5bbb3ba3f265da0aaa052dae

 

原文地址:https://www.cnblogs.com/lxlx1798/p/11220875.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇文章主要讲解了“FlutterComponent动画的显和隐怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究...
这篇文章主要讲解了“flutter微信聊天输入框功能如何实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“f...
本篇内容介绍了“Flutter之Navigator的高级用法有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处...
这篇文章主要介绍“Flutter怎么使用Android原生播放器”,在日常操作中,相信很多人在Flutter怎么使用Android原生播放器问题上存在疑惑,小编查阅了各式资料,整...
Flutter开发的android端如何修改APP名称,logo,版本号,具体的操作步骤:修改APP名称找到文件:android\\app\\src\\main\\AndroidManifest.xml
Flutter路由管理初识路由概念一.路由管理1.1.Route1.2.MaterialPageRoute1.3.Navigator1.4.路由传值1.5 命名路由1.6.命名路由参数传递1.7.适配二、路由钩子三、onUnknownRoute四、结尾初识路由概念路由的概念由来已久,包括网络路由、后端路由,到现在广为流行的前端路由。无论路由的概念如何应用,它的核心是一个路由映射表。比如:名字 detail 映射到 DetailPage 页面等。有了这个映射表之后,我们就可以方便的根据名字来完成路由的转发
前提:针对Android开发者(windows系统下),已安装Git,AndroidStudio(建议4.0+版本)一.下载Flutter SDK地址:https://flutter.dev/docs/development/tools/sdk/releases,在 Stable channel (Windows)里面下最新版本即可。Flutter的渠道版本会不停变动,请以Flutter官网为准。在中国,要想正常获取安装包列表或下载安装包,可能需要翻墙,也可以去Flutter github项目下去下载安
一、变量变量是一个引用,根据Dart中“万物皆对象”原则,即变量存储的都是对象的引用,或者说它们都是指向对象。1.1.声明变量://1.不指定类型var name = 'aaa';//2.明确指定类型String name = 'aaa';因为有类型推导,所以两种实现效果一样,官方推荐在函数内的本地变量尽量使用var声明。在变量类型并不明确的情况下,可以使用dynamic关键字//3.使用dynamic关键字dynamic name = 'aaa';1.2.默认值未初始化的变量
前言Flutter2.0发布不久,对web的支持刚刚进入stable阶段。初学几天,构建web应用时候碰到一些问题,比如中文显示成乱码,然后加载图片出现图片跨域问题:Failed to load network image...Trying to load an image from another domain?1.开启web端构建:使用下面这个命令才可以开启Web端构建的支持flutter config --enable-web提示我们:重新启动编辑器,以便它们读取新设置。2.重
一.Flutter打Android release包的步骤:1.为项目创建一个.jks签名文件(很简单,跳过)2.创建一个文件key.properties,直接复制下面key.properties位置如图:在里面输入一下内容:storePassword=iflytekkeyPassword=iflytekkeyAlias=teachingmachinestoreFile=E:/teacher/app/keys/TeachingMachine.jks输入你自己的passwork以及
1 问题Android原生向js发消息,并且可以携带数据2 实现原理Android原生可以使用RCTEventEmitter来注册事件,然后这里需要指定事件的名字,然后在js那端进行监听同样事件的名字监听,就可以收到消息得到数据Android注册关键代码reactContext.getJSModule(DeviceEventManagerModule.RCT...
1 Flexbox布局1) flexDirection 可以决定布局的主轴,子元素是应该沿着水平轴(row)方向排列,还是沿着竖直轴(column)方向排列2) justifyContent 决定其子元素沿着次轴(与主轴垂直的轴,比如若主轴方向为row,则次轴方向为column)的排列方式 有flex-start、center、flex-end、space-around...
1 实现的功能在网上看React Native文档,我特码就想实现一个页面到另外一个页面的跳转,然后另外一个页面怎么获取参数,特么没找到一个说清楚的,要么太复杂,要么说了不理解,下面是我自己写的一个App.js文件,实现一个Home页面跳到另外Details页面,并且携带了参数怎么在Details页面获取,就是这么简单粗暴.2 测试DemoApp.js文件如下...
1 问题在一个文件构建一个对象,然后在另外一个文件里面new这个对象,通过构造方法传递参数,然后再获取这个参数2 测试代码Student.js文件如下'use strict';import React from 'react'import {NativeModules, NativeEventEmitter, DeviceEventEmitter,Ale...
1 简单部分代码export default class App extends Component<Props> { render() { return ( <View {styles.container}> <View {styles.welcome}> &l...
1 怎么实现发送和接收事件理论上封装了Android原生广播的代码,需要注册和反注册,这里用DeviceEventEmitter实现//增加监听DeviceEventEmitter.addListener//取消监听//this.emitter.remove();这里可也可以通过安卓原生向页面js发送消息,可以参考我的这篇博客React Native之Android原生通过Dev...
1、Component介绍一般Component需要被其它类进行继承,Component和Android一样,也有生命周期英文图片如下2 具体说明1)、挂载阶段constructor()//构造函数,声明之前先调用super(props)componentWillMount()//因为它发生在render()方法前,因此在该方法内同步设置状态...
1 触摸事件普通点击我们可以使用onPress方法,我们可以使用Touchable 系列控件设计我们的按钮TouchableHighlight 背景会在用户手指按下时变暗TouchableNativeFeedback用户手指按下时形成类似墨水涟漪的视觉效果TouchableOpacity指按下时降低按钮的透明度,而不会改变背景的颜色TouchableWithoutFeedbac...
1 问题部分代码如下class HomeScreen extends React.Component { render() { return ( <View {{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Text>Home Scre...
1 Props(属性)和State(状态)和简单样式简单使用App.js代码如下/** * Sample React Native App * https://github.com/facebook/react-native * * @format * @flow */import React, {Component} from 'react';import {Pla...