人眼经过动态图形的视觉残留产生动感,因而有了动效.html
不管是在 AE & Animate 中创做图形,
调节关键帧设置变化函数;
仍是利用 PS 逐帧绘制导出 GIF,
本质上都是在产生一组连贯的序列画面.
动态图形也包含其中.
android
SVGA 最初就是为下降序列动画开销而生.
SVGA 描述了组成动效的基本元素 (位图 & 矢量),
又将其在时间轴上的表现 (alpha & matrix) 逐帧导出。
json
播放逻辑很是简单, 只需结合动效的每帧表现, 逐个渲染动画元素.
高还原动效的同时, 尽量复用动画元素, 进而从各个方面下降动效开销.
bash
"它是个转换插件,把设计师作的动画导出来,放到设备上去播放。"
网络
"它是一个客户端播放器,一种播放动效的方式,酱紫咱们就不用手撸动画,能够早点下班。"
编辑器
"它是一套协议,下降设计师与技术在动效方面的沟通成本"
svg
"它是一份解决方案,本质上解决的是图形效果与实现成本之间的矛盾问题。"
函数
做为一个客户端播放器,咱们能够从两个角度讨论 SVGA:工具
Animation(Player)
Content(Frames)
Tickers(FPS)
复制代码
.svga(Parser)
序列化
反序列化
复制代码
从播放器的角度 SVGA 是一种 (被优化过的) 序列帧动画,
经过一个被设置好间隔的 Ticker 推进序列帧播放。
性能
这时候有同窗要问,
"因此 SVGA 与咱们常见的序列帧动画有什么区别呢?"
从两个维度能够回答:
动画元素颗粒度(优化 1):
SVGA 颗粒很是细并且可控。
序列帧只有一层。
动画元素内容(优化 2):
SVGA 可使用矢量和位图结合,平衡 CPU & GPU 的开销。
序列帧只能用位图。
虽然也存在矢量序列帧,但不常见,这里不作讨论。
同一个动画,内容组织形式如图:
SVGA:
序列帧:
Lottie:
播放的时候也是如此:
把动画细分红各个元素,逐帧渲染每一个元素的动画,不动的就不须要从新渲染。
设计师电脑中常常会导出不少没法直接预览的 .svga 文件
"这些个不可预览的文件,里面装的究竟是什么东西呢?"
两年前我想过这个问题。
基于 “万物皆可解压” 的原则,
右键-打开方式-The Unarchiver
(╯‵□′)╯︵┻━┻z
解出来的是什么鬼,剧本不是这么写的啊!
这是由于解压的 .svga 是 2.x,
好奇的话可使用 1.x 文件解压一下。
2.x 的 .svga 是一个船新的版本,
使用的是当下最流行的 Protocol Buffers 来作序列化,
将素材和动效描述文件储存成二进制格式,天然没法直接解压。
复制代码
去除了 JSON 解析 SVGA 文件到底快了多少,
请见下文 1.x & 2.x 对比。
经过某种协议(Proto)
  把对象转换为字节序列的过程称为对象的序列化(Serialize)。
   把字节序列恢复为对象的过程称为对象的反序列化(Deserialize)。
   对象的序列化主要有两种用途:
  1) 把对象的字节序列永久地保存到硬盘上,一般存放在一个文件中;
  2) 在网络上传送对象的字节序列。
复制代码
举个栗子:
咱们经过步骤 一、二、3 将大象装进冰箱里。
装进冰箱就是序列化,
从冰箱里拿出来是反序列化,
而步骤 一、二、3,就是咱们商量好的协议,
若是不遵照这个协议,可能从冰箱里拿出来的就不是大象,
可能会拿出什么奇怪的东西。
属性包括了缩放、旋转、位移、透明度、颜色等等,
属性动画相关的 API 在 AE 和 客户端上是互通的,
导出以后能够直接赋值使用。
矢量是线性代数中研究的基本元素之一。
若是把矢量当作点跟原点的关系,
那么线性代数研究的问题能够理解为:
“一系列有关系的点在 二维(x y) 或者 三维(x y z) 坐标系中的图形特性。”
而一系列点之间的关系,就是函数。
贝塞尔多项式方程就是其中一种函数。
它的图形关系,也就是一系列点的关系图是:
因而可知,(What?)(╯‵□′)╯ ┴─┴
决定一条贝塞尔曲线的关键元素是:
本质上,这些点影响的是一个贝塞尔方程的多项式系数。
一阶贝塞尔曲线
starPoint: :P0
endPoint :P1
controllerPoint1 :P0 (重合)
controllerPoint2 :P1 (重合)
复制代码
二阶贝塞尔曲线
starPoint: :P0
endPoint :P2
controllerPoint1 :P1
controllerPoint2 :P1 (重合)
复制代码
三阶贝塞尔曲线
starPoint: :P0
endPoint :P3
controllerPoint1 :P1
controllerPoint2 :P2
复制代码
这样子的话,计算机中的全部线条, 均可以用:
var curve = new Bezier(
P0.x, P0.y,
P1.x, P1.y,
P2.x, P2.y,
P3.x, P3.y,
);
复制代码
建立了,万物皆是贝塞尔啊有木有!
┬─┬ ノ( ' - 'ノ) {摆好摆好)
而咱们平时在计算机中看到的线条,
或者设计师工具中用【钢笔工具】画出来的曲线:
这里有细心的同窗就要问了:
按上面说的,一条曲线只有四个点,
但咱们在 AE 中每拖一条线出来,
会有一个起点和一个终点,
这两个点分别有两个控制点,
酱紫就有六个点了,
这是咋回事啊?
拖动曲线的时候能够按 Alt 键将两个控制点分离,
而后你会发现,真正影响到当前曲线的只有:
也就是说,实际上在 AE 中也是符合咱们上面说的规律的。
那多出来的两个点又是什么呢?
它们分别是:
对当前曲线是没有影响的。
若是你用文本编辑器打开 SVG 文件(XML),
你会发现 SVG 中有一段:
M153 334
C153 334 151 334 151 334
C151 339 153 344 156 344
C164 344 171 339 171 334
C171 322 164 314 156 314
C142 314 131 322 131 334
C131 350 142 364 156 364
C175 364 191 350 191 334
C191 311 175 294 156 294
C131 294 111 311 111 334
C111 361 131 384 156 384
C186 384 211 361 211 334
C211 300 186 274 156 274
复制代码
里面的 M 对应的是绘制 API 的 MoveTo 方法:
- (void)moveToPoint:(CGPoint)point;
复制代码
C 对应的就是绘制贝塞尔曲线的:
- (void)addCurveToPoint:(CGPoint)endPoint
controlPoint1:(CGPoint)controlPoint1
controlPoint2:(CGPoint)controlPoint2;
复制代码
这里面少了的 starPoint 其实就是上一 endPoint 或者 movePoint,
**因此一个 C 里面三个点就足够了,
它们的顺序是:endPoint, controlPoint1, controlPoint2;
上面这两句话就是致使我这一个星期工做的罪魁祸首。
SVGA 中也一样使用了这份 Path 规范,
然而,在 SVGA 的转换器源代码中,发现
C(Curve) 的顺序是:controlPoint1, controlPoint2, endPoint;
而 M(MoveTo) 设置的点是:controlPoint1;
播放器也将错就错,自行更改了 C(Curve) 解析顺序:
这时 M(MoveTo) 使用的是点:controlPoint1,
导出来的动画长这个样子:
请用行列式求詹瞻心理的阴影面积...
修复方案固然是将 SVGA 中的 Path 修正回来...
路径修剪(TrimPath) 是一种矢量动效样式。
TrimPath 其实应该叫作 Trim Bezier,
SVGA 中的线条都是贝塞尔曲线。
它一共有三个相关的属性:
trimPathStart,
trimPathEnd,
trimPathOffset,
复制代码
它们分别表示 Path 从哪里开始,到哪里结束,距离起点多远。
至于怎么用,就看咱们的想象力了。
在 AE 形状图层中能够添加:
可添加在形状(Shape)属性中,也能够添加在 Shape 以外对多个 Shape 形成影响:
动效展现:
动效能够拆分红四个部分,
里面一个 Circle fill 的 Scale 动画
外面三个环绕 Circle stroke path 并添加 Trim & Width 动画
经过 SVGA Preview 咱们能够清晰了解它的结构:
接下来咱们经过 Android 的 PathMeasure (Web 太🐔b 难调试了)
来模拟 SVGA 还原这个动画的修剪效果。
这里实力安利业务中使用 SVGA 来一键还原这些效果,
(把锅完全甩给产品和设计,酱紫咱们就能够早点下班勒~😯)
TrimPathActivity
PathUtil 之后再讲。
···
蒙版和遮罩本质上是定向处理绘制图层的 aplha 通道。
在 AE 中经过面板设置蒙版属性:
转换器经过获取的参数,
在 iOS 和 Android & Web 上定制播放方案。
解决方案本质上都是经过获取的参数建立遮罩图层,
用遮罩图层对多个内容图层进行遮罩处理。
也能够能够经过设置蒙版属性:
控制图层的 alpha 通道,
达到只显示部分图案的效果。
"先定一个能达到的小目标, 好比动画达到 60 fps, 动画解析 100ms 内完成."
设备开销是一个很笼统的概念, 开销过大则设备卡顿,掉帧,发热,耗电,罪魁祸首,万恶之源。
从开发的角度来看,
文件大小, 解析耗时, 占用内存, CPU, GPU 都是能够衡量开销的维度,
如下从这几个维度对 1.x, 2.x, 序列帧 & GIF 作性能分析.
1.x 是 SVGA 最初的版本格式,
其实是由位图元素资源加上记录各元素每帧表现的 json 数据压缩成的 zip 包.
2.x 的 SVGA 将 json 格式的动画描述文件转成 protobuf 二进制文件,极大提升了文件的解码速度.
序列帧 & GIF 属于全帧位图,特色是文件大小随动效还原程度拔高,播放的过程当中会有长时间的内存高占用.
概要:
iOS 端:
Android端:
安卓 1.x 动效 CPU 占用表:
结论:
详细数据表