在互联网行业,特别是直播和视频类app中,酷炫的动画或者是图片的序列帧播放是必不可少的。
借鉴一下网上的图,公司项目图不能上传。感谢:
在业内的app中有可能解决方案,如下:
方案一:帧动画OpenGL加载;
方案二:属性动画;
方案三:Gif或WebP;
方案四:SVGA或者Lottie(两种原理相近但是SVGA效率更好)
对比以上:方案一、二、三:图片大小问题,播放资源占用高(当时测试的机子,内存占用约30MB/CPU占用约50%),gif效果差(只支持8位颜色)而方案四,解决了前面三个方案的问题。
SVGA 与Lottie对比(借鉴一下:感谢: )
从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所提供的动态文本、动态图像功能都是其它库所不能提供的。
我们最关心的永远是性能问题,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 一个文件,IOS,Android、WEB都可以使用。
SVGA可以很轻松的从远程下载动画资源进行播发,可配置性很高;
Lottie:可以参考:https://github.com/airbnb/lottie-android
SVGA:可以参考:http://svga.io/ 及https://github.com/yyued/SVGAPlayer-Android
具体的代码,等我请UED的同学给我设计一个SVGA文件后给出。
svga:
xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.gutao.svgademo.MainActivity"> <com.opensource.svgaplayer.SVGAImageView android:id="@+id/svgaImageView" android:layout_height="match_parent" android:layout_width="match_parent" android:background="#FFFFFF" /> android.support.constraint.ConstraintLayout>
public class MainActivity extends AppCompatActivity { private final String TAG = MainActivity.class.getSimpleName(); private SVGAImageView svgaImageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); svgaImageView = findViewById(R.id.svgaImageView); svgaImageView.setCallback(new SVGACallback() { @Override public void onPause() { Log.d(TAG, "onPause"); } @Override public void onFinished() { Log.d(TAG, "onFinished"); } @Override public void onRepeat() { Log.d(TAG, "onRepeat"); } @Override public void onStep(int i, double v) { Log.d(TAG, "onStep: i=" + i + " v=" + v); } }); svgaImageView.setLoops(1); SVGAParser parser = new SVGAParser(this); parser.parse("lock_air.svga", new SVGAParser.ParseCompletion() { @Override public void onComplete(@NotNull SVGAVideoEntity videoItem) { SVGADrawable drawable = new SVGADrawable(videoItem); svgaImageView.setImageDrawable(drawable); svgaImageView.startAnimation(); } @Override public void onError() { Log.i(TAG, "error"); } }); // svgaImageView.pauseAnimation();暂停动画 } }
SVGA demo 代码: https://github.com/gutaowqq20081010/svgaDemo/tree/master
目前先记录一下。
感谢:Pony&Clock
参考资料:
http://svga.io/
https://github.com/yyued/SVGAPlayer-Android
https://github.com/airbnb/lottie-android