Core Animation 简单记录
一. layer层
1.CAShapeLayer 通过矢量图形而不是bitmap来绘制的图层子类,绘制多边形,直线和曲线.
2.CATextLayer 绘制文本.
3.CATransforrmLayer
4.CAGradientLayer 渐变图层(绘制渐变).
5.CAReplicatorLayer 重复图层(生成许多相似的图层)
6.CAScrollLayer 小区域显示大图一部分
7.CATiledLayer 绘制高清大图
8.CAEmitterLayer 高性能的粒子引擎
9.CAEAGLLayer 用来显示任意的OpenGL图形
10.AVPlayerLayer (AVFoundation提供的)播放视频
二.CATransaction 动画
1.隐式动画
2.呈现图层和模型图层
3.显式动画
3.1属性动画
3.2关键帧动画
CABasicAnimation
CAKeyframeAnimation
CAPropertyAnimation
CABasicAnimation 和 CAKeyframeAnimation仅作用于单独的属性.
3.3 虚拟属性
transform.rotaion而不是transform
3.4 动画组 CAAnimationGroup
3.5 过渡
4.CATransition 过渡动画
(core Image)
三.图层时间
1.CAMediaTiming
anchorPoint 锚点定义??
2.相对时间
可独立地加速,延时或转移
beginTime 指定动画开始之前的延迟时间
speed 速度
timeOffset 从设置的时间开始循环一周
3.层级关系时间
beginTime, timeOffset speed属性将会影响到子动画.
4.全局时间和本地时间
马赫时间(全局时间) CFTimeInterval time = CACurrentMediaTime();
四.缓冲
1.CAMediaTimingFunction
五.基于定时器的动画
1.CADisplayLink
2.Chipmuck 物理引擎
六.性能调优
CPU VS GPU
CPU 中央处理器 软件层面
GPU 图形处理器 硬件层面
动画的舞台:
动画和屏幕上组合的图层实际上被一个单独的进程管理,而不是你的应用程序,iOS5之前的版本是SpringBoard进程,iOS6之后的版本叫做BackBoard.
当运行一段动画时候,这个过程会被四个分离的阶段被打破:
布局:这是准备你的视图/图层的图层关系,以及设置图层属性(位置,背景.边框等)的阶段.
显示:这是图层的寄宿图片被绘制的阶段.绘制有可能涉及你的-drawRect:和-drawLayer:inContext:方法的调用路径.
准备:这是Core Animation准备发送动画数据到渲染服务的阶段.这同时也是Core Animation 将要执行一些别的事务例如解码动画过程中将要显示的图片的时间点.
提交:这是最后的阶段,Core Animation打包所有图层和动画属性,然后通过IPC(内部处理通信)发送到渲染服务进行显示.
一旦打包的图层和动画到达渲染服务进程,他们会被反序列化来形成另一个叫做渲染树的图层树.渲染服务对动画的每一帧做出如下工作:
对所有的图层属性计算中间值,设置OpenGL几何形状(纹理化的三角形)来执行渲染.
在屏幕上渲染可见的三角形
一共六个阶段,前五个阶段在软件层面处理(通过CPU),最后一个阶段被GPU执行.你真正只能控制前两个阶段:布局和显显示.CoreAnimation框架在内部处理剩下的事务,你也控制不了它.
降低(基于GPU)图层绘制的方面有如下几种:
1.太多的几何结构–会引起CPU的瓶颈,限制一次展示的图层个数.
2.重绘–主要由重叠的半透明图层引起.
3.离屏绘制–这发生在当不能直接在屏幕上绘制,并且必须绘制到离屏图片的上下文中.
4.过大的图片–如果视图绘制超出GPU支持的20482048或者40964096尺寸的纹理,就必须要用CPU在图层每次显示之前对图片预处理,同样也会降低性能.
CPU的相关操作:
CPU的工作都发生在动画开始之前,它不会影响到帧率,但会延迟动画开始的时间,所以界面看起来会比较卡顿.
卡顿的原因有如下几个:
1.布局计算–如果你的视图层级过于复杂,当视图呈现或修改的时候,计算图层帧率就会消耗一部分时间.特别是iOS6的自动布局机制加强了CPU的工作.
2.视图懒加载–iOS只会当视图控制器的视图显示到屏幕上时才会加载它.这对内存使用和程序启动时间很有好处,但当呈现到屏幕上之前,按下按钮导致的许多工作都会不能被及时响应.
3.Core Graphics绘制–如果对视图实现了-drawRect:方法或者CALayerDelegate的-drawlayer:inContext:方法,那么在绘制任何东西之前都会产生一个巨大的性能开销.为了支持对图层内容的任意绘制,CoreAnimation必须创建一个内存中等大小的寄宿图片.然后一旦绘制结束之后,必须把图片数据通过IPC传到渲染服务器.在此基础上,Core Graphics绘制就会变得十分缓慢.
4.解压图片–PNG或者JPEG压缩之后的图片文件会比同质量的位图小得多.但是在图片绘制到屏幕上之前,必须把它扩展成完整的未解压的尺寸(通常等于图片宽x长x4个字节).为了节省内存,iOS通常直到真正绘制的时候才去解码图片.根据你加载图片的方式,第一次对图层内容赋值的时候,(直接或者间接使用UIIMageView)或者把它绘制到Core Graphics中,都需要对它解压,所以,对于一个较大的图片,都会占用一定的时间.
图层被成功打包,发送到渲染服务器之后,CPU仍然要做如下工作:为了显示屏幕上的图层,Core Animation必须对渲染树中的每一个可见图层通过OpenGL循环转换成纹理三角板.由于GPU并不知晓Core Animation图层的任何结构,所以必须要由CPU做这些事情.这是CPU涉及的工作和图层个数成正比,图层过多导致CPU每一帧的渲染.
IO相关操作:
上下文中的IO(输入/输出)指的是例如闪存或者网络接口的硬件访问.
IO比内存访问更慢.
Instruments工具
- Time Profiler --时间分析器
时间分析器工具用来检测CPU的使用情况.它可以告诉我们程序中的哪个方法正在消耗大量的CPU时间. - Core Animatiaon
提供了周期性的FPS,并且考虑到了发生在程序之外的动画.
Color Blended Layers – 基于渲染程度对屏幕中的混合区域进行绿到红的高亮(多个半透明图层的叠加).由于重绘的原因,混合对GPU性能会有影响,同时 也是滑动或者动画帧率下降的罪魁祸首之一.
六. 高效绘图-
软件绘图 – Core Animation的上下文中指代软件绘图(不由GPU协助的绘图).在iOS中,软件绘图通常是由Core Graphics框架来完成.相比Core Animation和OpenGL,Core Graphics要慢了不少.如果实现了CALayerDelegate协议中的-drawLayer:inContext:方法或者UIView中的-drawRect:方法(包装方法),图层就创建了一个绘制上下文,这个上下文需要的大小内存等于:图层宽图层高4字节,宽高的单位均为像素.图层每次重绘的时候都需要重新抹掉内存然后重新分配.
-
矢量绘图 – 包含一下几种:
任意多边形(不仅仅是一个矩形)
斜线或曲线
文本
渐变 -
脏区域-- 在实际应用中,鉴于非矩形区域边界裁剪和混合的复杂性,通常会区分出包含指定视图的矩形位置,而这个位置就是脏矩形.
当你检测到制定视图或图层的指定部分需要被重绘,你直接调用-setNeedDisplayInRect:来标记它,然后将影响到的矩形作为参数传入.这样就会在一次视图刷新时调用视图的-drawRect:(或图层代理-drawLayer:inContext:方法).
传入-drawLayer:inContext:的CGContext参数会自动被裁切以适应对应的矩形.为了确定矩形的尺寸大小,你可以用
CGContextGetClipBoundingBox()方法来从上下文获得大小.调用-drawRect()会更简单,因为CGRect会作为参数直接传入.- 异步绘制
UIKit单线程天性意味着寄宿图通常要在主线程上更新,这意味着绘制会打断用户交互,甚至让真个app看起来处于无响应状态.
七. 图像IO
如何优化从闪存驱动器或者网络中加载和显示图片.
1.线程加载
2.延迟解压–iOS通常会延迟解压图片的时间,直到加载到内存之后.这就会在准备绘制图片的时候影响性能.因为需要在绘制之前进行解压(通常是消耗时间的问题所在).
+imageNamed:方法避免延时加载该方法加载图片之后立刻进行解压.该方法只对从应用资源束中的图片有效.
另一种立刻加载图片的方法就是把它设置成图层内容,但需在主线程执行,所以不会对性能有所提升.
PVRTC 标准图片压缩.–PVRTC不用提前解压就可以被直接绘制 到屏幕上.
PVRTC的弊端:
1.1 加载消耗了更少的内存,PVRTC文件比JPEG要大,有时比PNG还要大,其压缩算法是针对与性能,而不是文件尺寸.
1.2 PVRTC必须是二维正方形,如果源图片不满足,则必须要在转换成PVRTC的时候强制拉伸或者填充空白空间.
1.3 质量并不是很好,尤其是透明图片.
1.4 PVRTC不能用Core Graphics绘制,也不能再普通的UIImageView显示,也不能直接用作图层的内容.必须要用作OpenGL纹理加载PVRTC图片,然后映射到一对三角板来CAEAGLayer或者GLKVieww中显示.
1.5 创建一个OpenGL纹理来绘制PVRTC图片大的开销相当昂贵.除非你想把所有图片绘制到一个相同的上下文,不然这完全不能发挥PVRTC的优势.
1.6解压时间过长.
七.图层性能
- 异步绘制
-
隐式绘制
1.1 使用特性的图层属性.
1.2 特定的视图.
1.3 特定的图层子类. -
文本
尽可能地避免改变那些包含文本的视图frame,这样做的话文本就需要重绘. -
光栅化
光栅化可以提供很大的性能优势,但是一定要避免作用在内容不断变化的图层上,否则它缓存方面的好处就会消失,而且会让性能变得更糟. -
离屏渲染
当图层属性的混合体被指定为在未预合之前不能直接在屏幕中绘制时,屏幕外渲染就被唤醒了.屏幕外渲染并不意味着软件绘制,但是它意味着图层必须在被显示之前在一个屏幕外上下文中被渲染(不论CPU还是GPU).图层以下属性将会触发屏幕外绘制:
圆角(当和maskToBounds一起使用时)
图层蒙版
阴影 -
混合和过渡绘制
为了加速处理进程,不到必须时刻不要使用透明图层,.任何情况下, 你应该这样做:
5.1 给视图的backgroundColor属性设置一个固定的,不透明的颜色
5.2 设置 opaque属性为YES
以此来减少 了混合行为. -
减少图层数量
初始化图层,处理图层,打包通过IPC发给渲染引擎,转化成OpenGL几何图形,这些是一个图层的大致资源开销. -
裁切
以下几种情况图层不可见:
–图层在屏幕边界之外,或者是父层边界之外.
–完全在一个不透明图层之后.
–完全透明. -
对象回收
主要体现在UITableView 和 UICollectionView,对象回收的基础原则就是你需要创建一个相似对象池.当一个对象的指定实例结束了使命,你把它添加到对象池中.每次当你需要一个实例时,你就从池中取出一个.当且仅当池中为空时再创建一个新的.
-