直播App中Android酷炫禮物動畫實現方案(下篇):SVGA由來與Lottie的對比
本文首發自我的微信公眾:技術視界(ID:clock_life)
在一個月黑風高的夜裡,一位開發Da Lao在朋友圈吐槽『你們UED設計的動畫,太炫了!我們實現不了……!』,接著小B(UED掌門人)與這位Da Lao談了一整晚的人生。
第二天,小B把Pony捉到了會議室,說道:『給你個死任務,把UED設計出來的動畫,實現到《ME直播》中,不然就拿你去祭天』。Pony差點當場就尿了……先給你看看,UED的動畫是醬紫的。
這個動畫,如果輸出成GIF的話,要3MB,尺寸是750*750。在上一篇文章中已經介紹過幾種被否掉的方法,這裡再稍作補充說明,如果使用GIF實現,有以下問題。
- 動畫文件太大(3MB的大小)
- 播放資源佔用高(當時測試的機子,內存佔用約30MB/CPU佔用約50%)
- 效果差(GIF只支持8位顏色)
那麼,使用WebP呢?嗯,使用WebP可以把動畫文件大小壓縮到一半,但是,播放資源佔用問題沒有解決,這依然是頭疼的問題,想想,一個視頻直播流已經佔用了系統給進程分配的大量內存,然後直播間裡面可能成千上萬甚至更大體量的人同時在線,觀眾們一個個贈送禮物的動畫出來,應用直接給搞掛掉了……
如果使用A-PNG呢?使用A-PNG可以完美地解決效果差的問題,因為PNG支持32位顏色啊,但是,同樣的天使動畫,大小可以達到9M,播放資源佔用更更更高!
探索
那麼,有沒有更好的方法去解決以上的問題?其實是有的,早在2015年,Adobe就已經把CreateJS收歸旗下,並且可以完美地將Flash動畫導出至Web中。也正是同一個時期,BodyMovin出現了,BodyMovin可以將另一個Adobe的軟體After Effects所設計的動畫完美地導出至Web中。這兩者的出現,是我們開發SVGA靈感的源泉。
具體的思路是,將動畫腳本導出,再將動畫元素(點陣圖)導出,然後在對應的客戶端,重新拼合這些點陣圖。這樣做的好處很明顯,元素是有限的,動畫腳本也非常輕量,我們只需要一次性地把元素還原出來就可以了。
相比序列幀,這種方案得到的動畫文件非常小,播放資源佔用也非常小,效果卻相當好(因為使用PNG支持32位顏色)。
實現
在2016年的時候,Lottie還沒開源,並且BodyMovin的文檔也相當欠缺,我們是不可能重新實現一個BodyMovin在iOS/Android上的播放器的。
於是,乾脆重寫一個?然後Pony就用了兩周的時間,把SVGA Flash轉換器寫出來了,再用兩周時間,把iOS和Android的Player也寫出來(當然,只是Demo階段)。一個月後,拿出來,給Da Lao們欣賞欣賞,Da Lao們都驚呆了……
這個方案,不僅資源佔用很小很小(當時測試的數據內存佔用約8M左右,CPU佔用約2%),文件大小也非常小(天使動畫只需295K),效果還狂拽酷炫高逼格。
緊接著接著,在YY內部就開始有了SVGA這個項目(當時沒有開源),經過了一整年的迭代,在YY系的產品中有超過十多個產品的使用,應用範圍涵蓋iOS/Android/Web/PC客戶端等。
SVGA與Lottie
在上一篇文章發出後,很多同學都在關注一個問題,SVGA和Lottie有什麼區別?嗯,沒有對比就沒有傷害,既然Lottie這麼強大,我們就用SVGA來跟它做一番對比,以下列了一些特性差異:
- 從CreateJS/Lottie實現的原理來看,都是將設計軟體中的時間軸完整地導出來,包括裡面的各種關鍵幀信息、矢量路徑、樣式等等。其中,最為關鍵的是『關鍵幀』!由於使用的是關鍵幀動畫描述,那麼對應的Player就難免變得複雜起來。如果只是簡單的一次線性方程,比如,物體從A點勻速移動至B點,還OK。但是,當遇到二次線性方程、貝塞爾曲線方程這些高階插值計算的時候,Player就會很吃力。(矢量動畫就是通過一些公式能表達的矢量線條和色塊,以此來表示每一幀動畫)
- CreateJS可以導出Flash動畫,Lottie可以導出After Effects動畫,但是它們都不能導出對方的動畫(每種設計工具的腳本都是不一致的),這也意味著,你家的設計師只能使用其中一種設計工具。
- Lottie在導出點陣圖動畫方面不夠友好,從UI設計師和開發人員使用角度來看都比較麻煩,開發人員需要先將做好的效果打包成ZIP,再解壓到本地目錄,才能播放。
- SVGA使用另外一套邏輯,它不關心關鍵幀,因為SVGA裡面的每一幀都是關鍵幀!也就是說,SVGA已經在導齣動畫的時候,把每一幀的信息都計算好了,如此一來,Player也就不用關心插值計算的過程。正因為如此,SVGA可以同時支持Flash和After Effects的導出,只需要在各自轉換器中計算差值就好了。
- SVGA在設計之初就支持點陣圖元素,在1.x格式時使用ZIP進行打包,在2.x格式中,直接使用ProtoBuf+Zlib方式打包,作為開發者,完全不用關心應該怎樣下載、解壓、獲取點陣圖文件,直接把svga文件扔進去Player就可以了。
- 功能上,SVGA更貼合直播應用場景,SVGA所提供的動態文本、動態圖像功能都是其它庫所不能提供的。
Android
我們最關心的永遠是性能問題,SVGA在設計之初就考慮到性能問題(這裡只討論Android端的實現)。Android端最初的SVGA Player是通過繼承SurfaceView(TextureView)實現的的,但是SurfaceView在硬體加速的情況下只能獨立於UI層級(在最頂或者最底),如果不開啟硬體加速渲染呢?效果會變得非常感人。並且在使用SurfaceView繪製Bitmap時,還伴隨著各種問題,包括內存回收、Activity生命周期以及UI層級各種牽扯不清的問題。
後期通過繼承重寫ImageView來實現Android端的SVGA Player,使用Canvas繪製Drawable的方式來繪製動畫,這樣也使得SVGA可以任意地嵌入到UI層級中,同時也解決之前諸多的存在問題。
當然,關於SVGA Player,UED還在不斷的繼續優化,大家可以持續關注官網和Github的更新...
生態
SVGA提供一整套的動畫解決方案,從設計、產品、開發三個環節保障動畫可快速落地。
為了讓設計師可以快速地導齣動畫,我們開發了Flash/After Effects插件。
http://svga.io/designer.html
為了讓開發者可以輕易地接入動畫,我們開源了iOS/Android/Web三個平台的源碼。
- https://github.com/yyued/SVGAPlayer-iOS
- https://github.com/yyued/SVGAPlayer-Android
- https://github.com/yyued/SVGAPlayer-Web
為了讓所有人都可以快速獲知動畫是否正常,動畫中的元素屬性,我們開發了動畫預覽器。
http://svga.io/svga-preview.html
為了解決設計師、開發者的疑難問題,我們還提供 Q 群服務576461005
所有的一切,都是為了文章最初的那句話,不要把Pony拿去祭天。
喜歡文章的讀者可以持續關注本專欄或微信公眾號:技術視界(二維碼)
推薦閱讀:
※理解 Android 新的依賴方式
※現在還有像WM系統一樣好用的通話自動錄音手機么?
※移動端消息推送 xmpp 和 mqtt 哪個更費電?