从 json 文件到炫酷动画 - Lottie 实现思路和源码分析
Lottie是最近Airbnb开源的动画项目,支持Android、iOS、ReactNaitve三个平台,相关背景介绍可以参考之前的文章Airbnb开源炫酷动画库Lottie(译)-看看Airbnb的工程师怎么说。本文分析主要Lottie把json文件转为动画的思路和源码实现。
文章首先介绍Lottie的基本使用,然后分析把json文件映射到动画的实现思路,最后分析Lottie的源码实现,这里分析的是Lottie-Android。
基本用法
与使用相关的只有三个类文件:LottieAnimationView、LottieComposition、LottieDrawable
,所以Lottie使用起来特别简单(需要注意Lottie支持API16及以上)。
最简单的使用方式是在xml中增加LottieAnimationView:
"Logo/LogoSmall.json"是需要加载的动画数据路径,根目录是assets目录。
也可以通过代码设置动画数据json路径:
然后在代码中控制动画播放或者添加监听事件:
Lottie提供了LottieDrawable可以使用:
可以看到Lottie使用起来非常简单,我们之后就从以上用到的LottieAnimationView、LottieComposition、LottieDrawable
入手来分析下Lottie动画的实现原理。
思路分析
我们先从底层思考下如何在屏幕上绘制动画,最简单的方式是把动画分为多张图片,然后通过周期替换屏幕上绘制的图片来形成动画,这种暴力的方式非常简单,但缺点明显,很耗内存,动画播放中前后两张替换的图片在很多元素并没有变化,重复的内容浪费了空间。
为了提高空间利用率,可以把图片中的元素进行拆分,使用过photoshop的同学知道,其实在处理一张图片时,可以把一张复杂的图片使用多个图层来表示,每个图层上展示一部分内容,图层中的内容也可以拆分为多个元素。拆分元素之后,根据动画需求,可以单独对图层,甚至图层中的元素设置平移、旋转、收缩等动画。
Lottie使用json文件来作为动画数据源,json文件是通过Bodymovin插件导出的,查看sample中给出的json文件,其实就是把图片中的元素进行来拆分,并且描述每个元素的动画执行路径和执行时间。Lottie的功能就是读取这些数据,然后绘制到屏幕上。
现在思考如果我们拿到一份json格式动画如何展示到屏幕上。首先要解析json,建立数据到对象的映射,然后根据数据对象创建合适的Drawable绘制到View上,动画的实现可以通过操作读取到的元素完成。
源码分析
1. json文件到对象的映射
Lottie使用LottieComposition
来作为After Effects的数据对象,即把json文件映射到LottieComposition
,LottieComposition
中提供了解析json的静态方法:
我们看下LottieComposition
都有哪些成员变量,这些成员变量描述了After Effects中的动画。
可以看到startFrame、endFrame、duration、scale等都是动画中常见的。我们看下List<Layer>
,看名字就是映射拆分后的图层数据:
Layer
中完成layer的json数据解析:
2. 数据对象到Drawable的映射
AnimatableLayer
继承自 Drawable
,我们看下它的子类:
其中LayerView
对应着Layer
数据,Layer
中有
对应的LayerView
中有
可以简单地理解为ViewGroup中可以包含ViewGroup或者View,但其实整个Lottie实现的动画都是绘制在一个View LottieAnimationView
上。
AnimatableLayer
的其它子类如 ShapeLayer,RectLayouer
等作为 LayerView
中List<AnimatableLayer>
的元素。
3. 绘制
LottieAnimationView
继承自 AppCompatImageView
,封装了一些动画的操作,如:
具体的绘制时委托为 LottieDrawable
完成的,我们看下 LottieDrawable
中的 draw()
方法:
LottieDrawable
继承自AnimatableLayer
,其draw()
方法如下:
可以看到先绘制了本层的内容,然后开始绘制包含的layers
的内容:
这个过程于界面中ViewGroup嵌套绘制类似。
实现分析
上面我们根据动画绘制的思路分析了下Lottie实现机制,下面从正面来捋一下程序的执行过程:
- 创建
LottieAnimationView lottieAnimationView
- 创建
LottieDrawable lottieDrawable
- 使用
LottieComposition
中的静态方法解析json文件创建LottieComposition lottieComposition
,这个过程中已经创建来多个Layer
对象。 lottieDrawable.setComposition(lottieComposition)
先清理之前的数据,然后开始buildLayersForComposition
,即根据lottieComposition
建立多个layerView
,此时已经创建好了多个Drawable,并通过List建立的为以lottieDrawable
为根的一个drawable树。
lottieAnimationView.setImageDrawable(lottieDrawable)
lottieAnimationView.playAnimation()
直接委托给了lottieDrawable
,lottieDrawable
中有private final ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
重点看下setProgress
方法
调用了private final List<KeyframeAnimation<?>> animations = new ArrayList<>()
的setProgress
:
在onValueChanged
时,各个创建好的Drawable会根据需求进行重绘,达到动画的效果。
Lottie把动画从View的动效转移到了Drawable上。
Lottie的性能
可以看到Lottie把json描述的动画数据映射到Drawable之后,实现动画时用到了ValueAnimator
,在动画更新时使用Drawable而非View,个人感觉在不需要交互时Drawable显然比View更加轻量。以下是Lottie性能的官方的说明:
- 如果没有mask和mattes,那么性能和内存非常好,没有bitmap创建,大部分操作都是简单的cavas绘制。
- 如果存在mattes,将会创建2~3个bitmap。bitmap在动画加载到window时被创建,被window删除时回收。所以不宜在RecyclerView中使用包涵mattes或者mask的动画,否则会引起bitmap抖动。除了内存抖动,mattes和mask中必要的bitmap.eraseColor()和canvas.drawBitmap()也会降低动画性能。对于简单的动画,在实际使用时性能不太明显。
- 如果在列表中使用动画,推荐使用缓存LottieAnimationView.setAnimation(String, CacheStrategy) 。
欢迎关注公众号wutongke,每天推送移动开发前沿技术文章:
推荐阅读:
Airbnb开源炫酷动画库Lottie(译)-看看Airbnb的工程师怎么说
从 json 文件到炫酷动画 - Lottie 实现思路和源码分析相关推荐
- android lottie字体json,从json文件到炫酷动画-Lottie实现思路和源码分析
从json文件到炫酷动画-Lottie实现思路和源码分析,Lottie是最近Airbnb开源的动画项目,支持Android.iOS.ReactNaitve三个平台,本文分析主要Lottie把json文 ...
- Android 炫酷动画APP,21 款炫酷动画开源框架,照亮你的APP
原标题:21 款炫酷动画开源框架,照亮你的APP 2017年安卓巴士全球开发者论坛-上海站 前言 最近对应用的UI视觉效果突然来了兴致,所以找了一些合适开源控件,这样更加省时,再此分享给大家,希望能对 ...
- canvas实现阿里云云栖大会炫酷动画效果
效果展示: 源码展示: <!doctype html> <html> <head><meta charset="utf-8">< ...
- 高级UI- 属性动画炫酷动画案例+淘宝动画+源码解析+策略模式使用
文章目录 属性动画源码: 案例1 案例2 最终效果 思路 : 代码 TODU 案例3 加载的炫酷动画. 以及策略模式的使用 效果图 思路 动画分析 先实现小圆的旋转动画, 开始在ondraw里面写动画 ...
- 【Qt炫酷动画】专栏导航目录
历时小半年,经过总结积累,详细剖析了Qt框架如何制作动画. 通过本专栏学习,可以学会如何diy窗体动画.控件动画 Qt动画 [Qt炫酷动画]专栏导航目录 [Qt炫酷动画]0.动画类简介 [Qt炫酷动画 ...
- 炫酷html动画,纯CSS3一个炫酷动画
纯CSS3一个炫酷动画 通过下边的代码可以看到这个例子的html代码还是很简单的,中间类似图标的部分是通过给两个 围绕盒子爬的虫子通过给 HTML代码 CSS代码 body{ margin: 0; b ...
- html舞动特效,7款纯CSS3实现的炫酷动画应用
原标题:7款纯CSS3实现的炫酷动画应用 HTML5确实非常强大,我们之前也分享过很多基于HTML5 Canvas的动画特效.但是你是否知道我们可以利用纯CSS制作一些很酷的动画效果?对,CSS3可以 ...
- SpringMVC关于json、xml自动转换的原理研究[附带源码分析 --转
SpringMVC关于json.xml自动转换的原理研究[附带源码分析] 原文地址:http://www.cnblogs.com/fangjian0423/p/springMVC-xml-json-c ...
- Android 之 Lottie 实现炫酷动画背后的原理
这是程序亦非猿的第 78 期分享. 作者 l 程序亦非猿 来源 l 程序亦非猿(ID:chengxuyifeiyuan) 转载请联系授权(微信ID:ONE-D-PIECE) 0. 前言 自我在内网发布 ...
最新文章
- PCL 点云 欧式聚类疑问
- lua 获取时分秒_PMON学用命令
- python内置函数用来打开或创建文件_2020年《python程序设计》基础知识及程序设计598题XS[含参考答案]...
- Hexo安装配置详解
- SAP Loyalty management模块演示场景的测试数据
- oracle9i的erp数据库无法正常关闭的解决方法。
- 亚马逊创始人贝佐斯离婚协议本周生效 前妻分得380亿美金
- python遥感影像分类代码_Python 实现遥感影像波段组合的示例代码
- Swift - 19 - 字典的初始化
- java毕业论文范文3_java毕业论文范文3篇
- Kali 2020 DHCP获取动态ip和静态IP设置方法
- 用C#获取系统中的临时文件夹或windows安装文件夹
- Unity3D FPS游戏之子弹贴图
- 基于Excel模板导出——ExcelTemplate
- IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! 解决办法
- html5调整文字段落之间的距离,css设置p段落上下间距距离
- 构建一个透明的activity
- win10-Administrator账户停用怎么重新启用(亲测有效)
- 【java】函数式接口和Stream
- android progressdialog 点击不消失,ProgressDialog不消失在Android应用程序
热门文章
- 执行Oracle中的sqlldr xxx.ctl命令导入数据时,当错误无法导入时,注意查看「xxx.log信息」
- 关于java重载函数,参数为null时,调用的处理。(精确性原则)
- Excel之【保护工作表】功能(工具----保护) ------可以防止修改格式,删除行。只能在里面填写数据。
- 抛弃百度UMEditor,拥抱summernote (解决上传文件又慢又卡的问题)
- Spring Boot学习——统一异常处理
- macOS Catalina下RX580/Vega系列显卡启动后DP输出黑屏和ALC1220声卡无法驱动的解决方案
- vue-cli3.x正确打包项目,解决静态资源与路由加载无效的问题,history模式下配合使用nginx运行打包后的项目
- 区域医疗移动医疗影像解决方案1-基于HTML5的PACS
- (转) Eclipse Maven 编译错误 Dynamic Web Module 3.1 requires Java 1.7 or newer 解决方案
- 如何在Java中分割字符串