引导页Gif动画调研

在app的引导页中,经常需要动态展示加载和交互过程,本文主要是对Gif动画的调研,技术要求如下:

  1. 支持复杂的动态效果
  2. 易于维护
  3. 易于开发
  4. 兼容iOS7和小屏
  5. 高性能

Gif动画

优点

使用Gif动画方式展示动态效果,具有很多优点,开发维护比较简单,工作量小,只需设计师提供动画即可,相比原生制作动画效率很高。Gif还能够实现很复杂、酷炫的动画特效,甚至有些是原生无法实现的。Gif对系统版本,对屏幕尺寸没有什么要求,兼容性较好。

缺点

当然Gif也存在一些缺点,它仅支持单页动画,对于连续性的多页面动画则无能为力,比如随着引导页滑动,一个按钮将从第一页飞到第二页。它的cpu使用率也比较高,每个Gif动画增加了26%的cpu利用率(模拟器iphone 5,ios10.3)。

对于开源的引导页类库,我们以EAIntroView为例,它的实现原理实际上是在一个scrollView容器上,平铺四个imageView和一个指式条,划动时切换到上/下一个页面。当使用Gif动画时,实际上将同时播放四个gif,因此造成CPU使用率较高,真机测试iOS10.3,iphone 6,cpu使用率70%左右。

优化

由于引导页的实现方式是将多个imageView同时放到scrollView上,造成几个Gif动画同时播放,CPU使用率较高。为了解决这个问题,现引入FLAnimatedImage库。这个库支持停止、播放动画。当划到某页时,才会去播放当前页的Gif动画,这样就降低了资源消耗情况,优化后cpu利用率降低到32%。

Gif实例

写了一个Demo,基于EAIntroView,功能尚不完善,仅仅用于验证实际效果。地址:https://github.com/superzcj/ZCJGifInIntroDemo

    self.gifArr = [NSMutableArray new];
    NSMutableArray *views = [NSMutableArray new];
    for (int i=0; i<4; i++) {
        
        NSString *imageName = [NSString stringWithFormat:@"guideImage_%d", i + 1];
        NSURL *url1 = [[NSBundle mainBundle] URLForResource:imageName withExtension:@"gif"];
        NSData *data1 = [NSData dataWithContentsOfURL:url1];
        
        FLAnimatedImage *image = [FLAnimatedImage animatedImageWithGIFData:data1];
        
        FLAnimatedImageView *imageView = [[FLAnimatedImageView alloc] initWithFrame:self.view.bounds];
        imageView.backgroundColor = [UIColor clearColor];
        imageView.animatedImage = image;
        
        UIView *bgView = [[UIView alloc] initWithFrame:self.view.bounds];
        [bgView addSubview:imageView];
        [views addObject:bgView];
        [self.gifArr addObject:imageView];
        
    }

代码如上,首先从本地读取Gif动画图片,生成FLAnimatedImage图片对象,再传递给FLAnimatedImageView以显示。为了在后面控制每个Gif对象的播放与停止,将Gif动画容器放入gifArr数组中。


    EAIntroPage *page1 = [EAIntroPage pageWithCustomView:views[0]];
    EAIntroPage *page2 = [EAIntroPage pageWithCustomView:views[1]];
    EAIntroPage *page3 = [EAIntroPage pageWithCustomView:views[2]];
    EAIntroPage *page4 = [EAIntroPage pageWithCustomView:views[3]];
    
    EAIntroView *intro = [[EAIntroView alloc] initWithFrame:self.view.bounds andPages:@[page1,page2,page3,page4]];
    [intro.skipButton setTitle:@"跳过" forState:UIControlStateNormal];
    [intro setDelegate:self];
    intro.tapToNext = YES;
    
    [intro showInView:self.view animateDuration:0.3];

创建四个引导页页面,将上面生成的页面内容传递进来,最后将引导页添加到页面上。


- (void)intro:(EAIntroView *)introView pageAppeared:(EAIntroPage *)page withIndex:(NSUInteger)pageIndex {
    NSLog(@"Current page index = %lu", (unsigned long)pageIndex);
    
    for (FLAnimatedImageView *iv in self.gifArr) {
        [iv stopAnimating];
    }
    FLAnimatedImageView *imageView = self.gifArr[pageIndex];
    [imageView startAnimating];
    
}

滑动引导页时,停止所有的Gif动画,只播放新出现的当前页动画。

FLAnimatedImage

FLAnimatedImage是由Flipboard开源的iOS平台上播放GIF动画的一个优秀解决方案,在内存占用和播放体验都有不错的表现。它在Github上的Star有5461个,被Facebook、Dropbox等应用引用。

FLAnimatedImage的实现原理很简单,只有两个类,FLAnimatedImage负责解析GIF动画数据,读取Gif中的每一帧图片,FLAnimatedImageView则展示FLAnimatedImage处理后的动画数据,控制Gif动画的播放、停止等。

FLAnimatedImage利用CGImageSource获取图像对象、图片属性信息等,调用CGImageSourceCopyProperties方法获取到Gif动画循环次数,调用CGImageSourceCreateImageAtIndex取得帧图片,然后根据GIF图的大小和缓存策略判断需要缓存的单帧图片数量,缓存起来。

FLAnimatedImageView是UIImageView的子类,完全兼容UIImageView的各个方法。它设置GIF动画的封面帧图片,当前帧索引,GIF动画的循环播放次数,播放时间累加器,更新是否发起动画的标志位,判断是否启动GIF动画。

第三方库动态引导页

使用第三方的动态引导页类库,能大大提升开发效率。

JazzHands是一个动态引导页类库,它是基于关键帧的动画框架, 可以用于手势,滚动视图,KVO或者ReactiveCocoa, 十分方便。它在Github上star数有6102,在引导页类库中最受欢迎。

官方提供了一个很酷炫的Demo,地址:https://github.com/IFTTT/JazzHands。

总结

Gif动画 第三方库(JazzHands) 动画
开发工作量 极高
维护工作量 极高
cpu利用率和内存占用 高(26%的cpu利用率) 低(cpu使用率在10%)
兼容性 支持iOS7,支持小屏幕 支持ios7,支持小屏幕 支持
适用性 仅支持单页动画 支持多种类型动画 无限制

你可能感兴趣的:(引导页Gif动画调研)