人眼經過動態圖形的視覺殘留產生動感,因而有了動效.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 佔用表:
結論:
詳細數據表