iOS中动图原理探究

本系列博客是本人的开发笔记。为了方便讨论,本人新建了一个微信群(iOS技术讨论群),想要加入的,请添加本人微信:zhujinhui207407,【加我前请备注:iOS 】,本人博客http://www.kyson.cn 也在不停的更新中,欢迎一起讨论

在开发iOS的过程中一开始只是讲求功能的完善,后期会逐渐对UI的展示提出越来越高的要求。大家可能首先会想到动画,比如CAAnimation,OpenGL等库。但有时为了偷懒,或者有特别难以实现的动画我们可以通过动图来实现。本文就动图实现的原理以及各种方案做个探究。

原理

大家都知道,动图是由一张张静态图片在一定时间内播放形成的。其中的每一张静态图片我们称为一帧(Frame),播放出来的动画也称为逐帧动画。iPhone的每秒帧数是60,当每秒播放帧数(FPS:Frames Per Second)低于24的时候就会给人以卡顿的感觉。因此假设我们有个ImageView,如果我们循环往复的按同等时间间隔替换里面的图片,那按道理就会给我们一种动画的感觉:

iOS中动图原理探究_第1张图片
逐帧动画

具体实现

UIKit

UIImageView 已经为我们提供了相应的加载动图的属性:

属性 含义
animationImages 图片数组
animationDuration 持续时间
animationRepeatCount 重复次数

相应地,UIImage中也提供了对动画的支持:

方法或属性 含义
animatedImageNamed: duration: 动图初始化
images 包含的图片数组(如果有)

因此我们只需要准备一系列的JPG或PNG图片数组,然后将其依次加载并添加进数组中,设置好动画时间以及其他的一些参数即可实现。

Gif

UIImage本身不支持加载Gif,如果使用[UIImage imageWithData:];方法只会加载Gif的第一帧。幸好SDWebImage已经支持了加载Gif图:

NSData *imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage sd_animatedGIFWithData:imageData];
imageView.image = image;

如果我们查看SDWebImage的源码会发现其原理跟本文第一种方式是类似的,都是先获取每一帧,然后将其赋值给UIImageView

方法 介绍
CGImageSourceGetCount 获取帧数
[UIImage imageWithCGImage:imageRef] 获取每一帧图像

表中的imageRef是通过CoreGraphics中提供的方法获取的图片引用。这里不多做介绍,大家可以参考苹果官方文档。

WebP

使用Gif的缺点是图片太大,文件加载也会消耗I/O资源。因此谷歌设计了另外一个图片格式:WebP,它的优点在于更优的图像数据压缩算法,更小的图片体积,而且拥有肉眼识别无差异的图像质量。下图展示了一份Gif与WebP的图片对比图:

iOS中动图原理探究_第2张图片
Webp VS gif

目前谷歌的全系列产品都支持WebP格式,也为谷歌带来了很多效益。不过iOS系统对于WebP的支持并不是特别理想,系统没有提供对应的支持。我们只能通过SDWebImage来实现WebP图片的加载:

  1. 通过pod 'SDWebImage/WebP'SDWebImage支持WebP。
  2. 通过sd_setImageWithURL实现对WebP图片的加载。

总结

本文介绍了iOS中动图的加载方式及其原理,作为对动画的一个补充,动图在某些场合还是比较简单高效的。但逐帧动画相对于关键帧动画(对关键帧动画不了解的同学可以自行谷歌)确实性能差很多,因此大家谨慎选择。为了便于大家理解,我写了一个和本文配套的Demo:https://github.com/zjh171/WebPDemo,希望对大家有所帮助。

参考

GIF图形文件格式文档

你可能感兴趣的:(iOS中动图原理探究)