美文网首页
Core Animation编程指南

Core Animation编程指南

作者: 钱嘘嘘 | 来源:发表于2016-02-08 17:57 被阅读569次

    Core Animation编程指南

    关于Core Animation


    Core Animation自身并不是一个绘图系统。它只是一个负责在硬件上合成和操纵应用内容的基础构件。Core Animation的核心是图层对象,图层对象用于管理和操控你的应用内容。图层将捕获的内容放到一副位图中,图形硬件能够非常容易的操控你的位图。在大部分应用中,图层被作为一种管理视图内容的方式,但是你也可以创建标准的图层,这取决于你自身的需要。

    隐式动画是一种从旧属性值动画到新属性值的动画形式。

    该文档为那些需要更全面的控制动画效果或打算利用图层提升绘图性能的开发者.

    Core Animation基础


    图层是绘图与动画的基础


    基于图层的绘图模型

    对基于视图的绘图,对视图的改变经常会触发调用视图的drawRect:方法以重绘视图内容。但是此种方式的代价相对较高,因为它是CPU在主线程上的操作。Core Animation通过尽可能的使用图形硬件操纵缓存后的位图来避免了这种开销,从而完成相同或相似的效果。

    基于图层的动画

    可在图层上执行的动画类型:移动,缩放,旋转,透明度,圆角半径,背景颜色

    图层对象定义了自己的几何结构


    图层使用两种类型的坐标系统

    图层利用基于点的坐标系统单位坐标系统指定内容的布局,当指定的值是直接映射到屏幕或相对于其他图层的坐标,图层的position属性,则使用基于点的坐标系统,与屏幕坐标不相关联,则使用单位坐标。比如图层的anchorPoint属性。

    锚点是使用单位坐标系统的属性之一。

    锚点影响几何结构的操作

    position属性是相对于图层的锚点被指定。并且任何你对图层阴影的变换操作也是相对于锚点。

    AnchorPoint相对于自身wh的百分比,0.0~1.0,position是相对于父视图的坐标点。

    图层可在三维空间中操作

    CALayer的transform属性用来指定应用到图层和它内嵌的子层上的变换。通常当你想更改图层本身则使用该属性。sublayerTransform属性定义了仅应用在子层上的变换以及给场景内容添加透视效果。

    如果是旋转,应用一个旋转角度的正弦和余弦值.

    不同的图层树反映了不同的动画状态


    使用Core Animation的app拥有三个图层对象集合。每一个图层对象集合在呈现app内容上都扮演着不同的角色。

    模型图层树

    模型对象负责存储所有动画的目标值

    呈现树中的对象包含所有运行中的动画的瞬时值

    渲染树中的对象执行实际的动画,并且对Core Animation是不公开的

    你可能为了优化app内容的性能而选择加入图层对象而非视图,原因在于图层的开销要比视图低。

    app主要与图层树中的对象进行交互,但可能有时会访问呈现树中的对象。具体地,访问图层树中对象的presentationLayer属性将返回一个在呈现树中相对应的对象。你可能会通过该对象获取在动画执行过程中的某一时刻的属性值。

    重要:只在动画运行时访问呈现树中的对象。当动画在进行中,呈现树就包含了图层显示在屏幕上的那一刻的值。该行为与图层树不同,图层树永远只表示最终的目标值。

    图层与视图的关系

    图层不是视图的替代品。因此无法创建一个基于单一图层对象的可视界面。图层是视图的基础设施。具体地,图层让视图的绘图和动画更简单和高效,并且能在绘图和动画时保持高帧率。然而许多事情图层无法做到。图层不能处理事件、绘制内容,特别是在响应链中,或是做一些其他的事情。因此,每个app必须有一个或多个视图来处理这类交互。

    在iOS中,每一个视图有一个相对应的图层对象。

    比如说,如果你想使用相同的图片在多个地方,你可以只加载图片一次,然后将图片和多个独立的图层对象相关联,最后添加这些图层对象到图层树中。每一个图层只会引用源图片而不是尝试在内存中创建自身对图片的拷贝。

    构建图层对象


    开启对Core Animation的支持

    iOS是自动支持图层的

    改变与视图相关联的图层对象

    改变视图自有的图层类

    你可以通过覆盖iOS视图中的layerClass方法并返回一个需要的图层类对象。默认是CALayer。以下情况需要自定义图层类对象:

    (1)视图的绘图内容是由OpenGL ES实现,此种情况你需要使用CAEAGLLayer对象。

    (2)特殊的图层让你拥有更强的表现性能。

    (3)需要利用某些特殊的Core Animation类,比如粒子发射器或者拷贝器。

    不同的图层拥有特定的行为

    提供图层的内容

    图层是管理app内容的数据对象。图层的内容由包含可视数据的位图构成。

    (1)直接赋值一个UIImage对象给图层对象contents属性。(这个技术适用于图层内容从不或几乎不改变的情形。)

    (2)赋值一个代理给图层,由代理负责绘制图层内容。(该技术适用于图层内容可能偶尔改变,且内容可由外部对象提供,比如视图。)

    (3)定义一个CALayer的子类并覆盖类的绘图方法,有覆盖的方法返回图层的内容。(该技术适用于你需要创建自定义图层的子类,或者你想改变图层基本的绘图行为。)

    使用图片为图层提供内容

    当赋值图片时,记住提供的图片的分辨率要与本地设备的分辨率相匹配。对于Retina显示设备,这可能也需要你去调整图片的contentsScale属性


    使用代理提供图层的内容

    图层的内容是动态改变的,调用delegate方法来填充:

    (1)如果你的代理实现了displayLayer:方法,实现方法负责创建位图并赋值给contents属性。(CG需要自建上下文再绘制,UIKit直接绘制)

    (2)如果你的代理实现的是drawLayer:inContext:方法,Core Animation创建一个位图,创建一个用于绘制位图的上下文,并调用代理方法填充该位图。你的代理方法所要做的是将内容画在图形上下文上。(CG拿上下文来绘制,UIKit要转换上下文为当前上下文来绘制)

    覆盖displayLayer:方法在当你的app更倾向于载入或创建想要显示的位图的情况下适用。

    如果你没有预渲染的图片或者辅助对象来创建位图。代理对象可以使用drawLayer:inContext:方法动态的绘制内容。

    有图层的视图,是其代理,实现drawRect:

    由子类提供图层的内容

    如CATiledLayer类通过将大图片拆成更小的可管理、可独立渲染的碎片来管理大的图片。因为只有图层知道在某一时刻哪一个碎片需要被渲染,图层会直接管理绘图的行为。

    子类化图层类,你可使用下述的两种方式绘制你的图层内容:

    (1)覆盖图层的display方法并使用在方法中直接设置图层的contents属性。

    (2)覆盖图层的drawInContext:方法并将需要的内容绘制到提供的图形上下文中。

    用哪种方式取决于绘图过程的控制力

    display方法是更新图层内容的主要入口点,所以覆盖这个方法让你处于完全的过程控制中。覆盖display方法也意味你需要负责contents属性创建CGImageRef对象

    如果你只是想绘制内容(或让你的图层管理绘图操作),你可以覆盖drawInContext:方法并让图层为你创建内容储备。

    调整提供的内容

    当给图层的contents属性赋值一个图片,图层的contentsGravity属性确定图片如何适合当前的边界。使用contentsGravity属性来确定你的内容以最佳的呈现方式。

    你可以向contentsGravity属性赋予的值分为两个分类:

    (1)基于位置的引力约束允许你固定你的图片到图层矩形边界的一个特殊的边缘或角落,不会缩放图片。-- Top,TopLeft/Right,Left,Right,Center,Bottom,BottomLeft/Right。

    (2)基于缩放的引力约束允许你伸缩图片使用多个选项之一,某些选项保留长宽比,有些则不保留。-- kCAGravityResizeAspectkCAGravityResizeAspectFillkCAGravityResize

    图层的contentsGravity属性被设置为kCAGravityResize常量值,它是唯一一个不保留图片的长宽比的选项。

    使用高分辨率的图片

    图层不知道当前设备的分辨率信息。图层只是简单的存储一个指向位图的指针,并用给定的有效像素以最佳的方式显示。如果你赋值一个图片给图层的contents属性,你必须给图层的contentsScale属性设置一个正确的值以告诉Core Animation关于图片的分辨率。默认1.0,Retina-2.0。使用[[UIScreen mainScreen] scale]可获取正确的缩放率。

    调整图层的可视样式和外观


    图层对象拥有内建的可视装饰,如边框、背景色。你可以使用这些装饰对图层的主内容进行补充。因为这些可视的装饰不需要任何渲染。

    图层拥有自己的背景和边框

    背景被渲染在图层的内容图片的后方,边框被渲染在内容图片的前方。

    注意使用模式图片时,渲染是由Core Graphics完成,它使用的是标准坐标系统。渲染结果是颠倒的。可以使用[backgroundLayer setTransform:CATransform3DMakeScale(1.0, -1.0, 1.0)];

    opaque == YES,提升性能。给图层设置了非零的圆角半径,则不可以将图层标记为不透明类型。


    图层支持圆角半径  --  cornerRadius

    圆角半径不影响图层的contents属性中得图片,除非masksToBounds属性被设置为YES。

    图层内建支持阴影

    CALayer类包括若干个配置阴影的属性。使用图层你可以控制阴影的颜色,相对于图层内容的位置(shadowOffset)透明度(shadowOpacity)以及形状

    如果你启用了图层的masksToBounds属性,围绕边缘的阴影将被裁减掉。如果既想要阴影又要启用maskToBounds为YES,那么你可以使用两个图层。第一个是包含内容的图层,将该图层的maskToBounds属性设置为YES,然后创建一个相同尺寸且含有阴影效果的第二个图层,最后调用第二个图层的addSublayer方法将第一个图层嵌入到第二个图层中就可以了。

    注意:iOS平台上不能给图层添加滤镜

    给图层添加自定义属性

    CAAnimation和CALayer类扩展了键值编码--KVC以对自定义属性进行支持。你可以使用该行为给图层添加数据并使用你定义的键检索对应的值。你甚至可以给你的自定义属性关联动作,当该属性的值发生变化,对应的动画将会被执行。

    图层的内容动画


    改变图层框架矩形的尺寸,改变其在屏幕上的位置,应用旋转变换,改变它的透明度。

    用简单的动画表现图层属性的变化  --  CABasicAnimation


    你可以以显式或隐式的执行简单的动画。隐式动画使用默认的定时器动画属性展现动画。而显式动画需要你为动画对象配置一些参数。所以当默认的定时器能够很好的为你服务并且你所要的动画效果不需要太多代码时,隐式动画则非常的适合你。

    为了触发隐式动画,你所要做的是更新图层对象的属性。

    为了显式地使用动画对象呈现相同的变化,创建一个CABasicAnimation对象并配置该对象的动画参数。为了执行一个动画,你使用addAnimation:forKey:方法将动画对象添加到你想要展现动画的图层上。

    不同于隐式动画,隐式动画会更新图层对象的值(就是直接赋值)。而显示动画不会更改图层树中的数据。显示动画仅是创建了一个动画。要手动改变值。


    用关键帧动画表现图层属性的变化  --  CAKeyfarmeAnimation


    显示了一个图层position属性的5秒动画。position是动画跟随一个路径。使用一个CGPathRef数据类型指定的。--  其实就是原来用CG画图的,现在把过程改成动画。

    指定关键帧的值

    指定关键帧值的主要方式以对象数组作为它的值。但是对于包含CGPoint数据类型(比如图层的anchorPoint属性和position属性),你可以指定一个CGPathRef数据类型替代。

    关键帧值数组 -> 然而一些对象必须在添加到数组中之前被转换为id类型,所有标量类型或结构体必须被包装为对象,比如:

    (1)对于属性类型为CGRect(例如bounds和frame属性),使用NSValue对象包装每一个矩形。

    (2)对于图层的变换属性,使用NSValue包装每一个CATransform3D矩阵。动画这个属性将引起关键帧动画给图层轮流应用每个变换矩阵。

    (3)对于borderColor属性,在添加到数组之前,转换CGColorRef数据类型为id类型。

    (4)对于属性为CGFloat类型,在添加到数组之前,使用NSNumber包装每个值。

    (5)为了动画图层的内容属性,指定一个CGImageRef数据类型属性。

    对于一个CGPoint数据类型的属性,你可以创建一个点(使用NSValue对象包装)数组,OR 使用CGPathRef对象指定跟踪的路径。<1> 当你指定一个点数组,关键帧动画对象在每一个连续的点之间绘制一条线,并沿着这些线移动。<2> 当你指定一个CGPathRef对象,动画起始于路径的开始点并跟随路径线移动,这包括沿着任何曲面。你可以使用开放的或者封闭的路径。

    有没有的框架可以简化这种封装?????

    指定关键帧动画的定时器

    关键帧动画的定时与步调比基本动画来的要复杂。以下是几个用于控制定时和步调的属性:

    calculationMode属性定义了计算动画定时的算法。该属性值会影响其他与定时相关属性的使用方式。

    (1)线性和曲线动画,动画的calculationMode属性被设置为kCAAnimationLinearCAAnimationCubic,属性值被用于提供定时器信息以生成动画。这些模式值让你最大化控制动画的定时器。

    (2)节奏动画,动画的calculationMode属性被设置为kCAAnimationPacedkCAAnimationCubicPaced,这些属性值不依赖由keyTimes或timingFunctions属性提供的额外定时器值。相反,定时器值被隐式地计算以提供一个常速率动画

    (3)离散动画,动画的calculationMode属性被设置为kCAAnimationDiscrete,该值将引起动画属性从一个关键帧跳到另一个没有任何补间动画的下一个关键帧。计算模式使用keyTimes属性值,但忽略timingFunctions属性。

    (4)keyTimes属性为应用在每一关键帧指定应用到每一个关键帧上的计时器。该属性只在calculationMode属性被设置为kCAAnimationLinear,kCAAnimaitonDiscrete,kCAAnimationCubic时被使用。它不使用在节奏动画中。

    (5)timingFunctions属性指定使用在每一个关键帧部分的定时曲线(该属性替换了继承的timingFunction属性)。

    如果你想自己处理动画的定时,可以使用kCAAnimationLinear或kCAAnimaitonCubic模式与keyTimes和timingFunctions属性。keyTimes定义了应用在每一关键帧的时间点。所有中间值的定时由定时函数控制,定时函数允许你对各个部分应用缓入或缓出曲线定时。如果你不指定任何定时函数,动画将会是线性的。


    停止一个隐式动画的运行

    提前停止动画:

    (1)为了从图层上移除单独的动画对象,调用图层的removeAnimationForKey:方法移除你的动画对象。该方法使用的键要与调用addAnimation:forKey:方法传入的键一致。你指定的键必须不为nil。

    (2)为了移除图层的所有动画对象。调用图层的removeAllAnimations方法。该方法立即会移除所有进行中的动画,并使用图层当前的状态信息重绘图层。

    外观突然的跳跃 -- 呈现树中的对象的最终值...More

    同时动画多个属性变化  --  CAAnimationGroup

    有点像dispatch_group。更高级的可以用一个事物对象。


    检测一个动画的结束  --  block 和 delegate

    Core Animaiton提供对动画开始与结束的检测支持。比如说你可能使用开始通知设置一些相关状态信息,使用对应的结束通知清理这些状态。

    (1)使用setCompletionBlock:方法添加一个完成block给当前的事务。当事务中的所有动画完成后,事务将执行你的完成块。

    (2)给CAAnimaiton对象赋值一个代理,该代理实现了animationDidStart:方法和animaitonDidStop:finished:代理方法。

    两个动画链接在一起使用,动画对象的beginTime属性在希望的时间启动动画。为了将两个动画链接在一起,设置第二个动画的开始时间为第一个动画的结束时间。

    如何动画有图层支持视图

    iOS中图层更改的规则

    [UIView  animateWithDuration:1.0  animations:^{}];

    记住将更新视图约束作为动画的一部分


    构建图层层级


    将图层排列为图层层级

    添加、插入、移除子图层

    addSublayer:

    insertSublayer:above:  --  insertSublayer:atIndex:  --  insertSublayer:below:图层的可视性主要由它的zPosition属性决定,然后是由其在子图层数组中的位置决定。

    removeFromSuperlayer

    replaceSublayer:with

    子图层的位置与尺寸

    bounds && position

    图层层级对动画的影响

    speed动画运行速度。

    调整你的图层层次的布局

    如果你的app的图层都是与视图相关,使用基于图层的布局支持对你的视图尺寸与位置的更新,以应对尺寸与位置的变化。

    手动规划你的图层层次

    你可以通过在父图层的代理对象上实现layoutSublayersOfLayer:方法手动处理布局。

    实现一个自定义图层子类,你的子类可以覆盖layoutSublayers方法并使用该方法(而不是代理)去处理任何布局任务。子图层的定位进行完全的控制的情况下,你只需要覆盖这个方法。


    子图层与裁剪


    与视图不同的,一个父图层不会自动地裁剪超出其边界的子图层的内容。默认情况下,父图层允许他的子图层完全的被显示。通过设置图层的masksToBounds属性为YES,你可以重新启用裁减功能。

    masksToBounds  --  裁剪蒙版含义

    在图层之间转换坐标值

    某图层中的一个坐标值转换为屏幕坐标位置相同而处在不同图层的一个坐标值。CALayer提供了一组简单的转换方法以应对这种情况:

    (1)convertPoint:fromLayer:

    (2)convertPoint:toLayer:

    (3)convertRect:fromLayer:

    (4)convertRect:toLayer:

    在两个图层之间转换时间,使用convertTime:fromLayer:与convertTime:toLayer:方法。

    高级动画技巧


    过渡动画支持改变图层的可视性

    一个过渡动画对象为图层创建一个可动画的可视过渡。与基于属性的动画不同,一个过渡动画操纵一个图层的缓存图片以创建可视效果,如果通过单独的改变属性实现会非常的困难,也许根本无法实现。标准的过渡类型包括:将旧视图移开显示新视图、推入、移动、淡入淡出动画。

    为了实现一个一个过渡动画,创建一个CATransition对象,然后添加该对象到包含过渡特效的图层上。你使用过渡对象指定所要执行的过渡类型以及过渡动画的开始点和结束点

    自定义动画的定时

    时间系统是动画的一个重要部分。通过Core Animation方法和CAMediaTiming协议可为动画指定精确的时间信息。共有两个Core Animation类适配该协议。其中之一是CAAnimation类,所以你可以在动画对象中指定时间信息。其二是CALayer,你可以为隐式动画配置一些与时间相关的功能。

    为了帮助你确定一个图层的适当时间值,CALayer类定义了convertTime:fromLayer:以及convertTime:toLayer:方法。

    CFTimeInterval  localLayerTime = [myLayer  convertTime:CACurrentMediaTime() fromLayer:nil];

    (1) 使用beginTime属性设置动画的开始时间。如果你延时了动画的开始。你可能也想设置fillMode属性为kCAFillModeBackwards。

    (2) autoreverses属性引起一个动画在指定的持续时间内执行并返回到动画的开始值。你可以将此属性与repeatCount属性联合使用,让动画在开始与结束值之间反复来回。

    对动画组中的动画使用timeOffset属性,让动画一开始就出现在以后某时刻才会出现的状态。其实就是偏移。

    暂停与恢复动画

    为了暂停一个动画,你可以利用图层适配CAMediaTiming协议这一点,设置图层动画的速度为0.0。非0就开始动画。

    显式事务可以改变动画的参数

    对图层属性的每次更改都是事务的一部分。CATransaction类管理动画的创建和分组并在适当的时间执行动画。可以创建显式事务以能够更精确的管理动画。

    使用CATransaction类提供的方法创建与管理事务。通过调用begin类方法,可以开始(或隐式地创建)一个新的事务;调用commit类方法可结束一个事务。

    kCATransactionAnimationDuration

    [CATransaction begin];

    [CATransaction setValue:[NSNumber numberWithFloat:10.0f];

    forKey:kCATransactionAnimationDuration];

    [CATransaction commit];

    给动画添加透视

    当更改一个场景的透视,你需要更改被观察图层的父图层subLayerTransform矩阵。

    改变一个图层的默认行为

    Core Animation使用动作对象为图层实现了隐式动画行为。动作对象服从CAAction协议并定义了一些运行于图层的相关行为。所有CAAnimation对象都实现了这个协议

    自定义适配CAAction协议的动作对象

    适配CAAction协议并实现runActionForKey:object:arguments:方法。在该方法中利用可用的信息执行任何你想要在图层上的动作。

    当你定义了一个动作对象,你必须决定动作以何种方式被触发。动作的触发器定义了你用于注册动作的键。下面被触发:

    (1)图层的某一个属性值被改变。识别动作的键是属性名。

    (2)图层变成可视或被加入到图层层次中。则识别动作的键为kCAOnOrderIn。

    (3)图层从图层层次中被移除。则识别动作的键为kCAOnOrderOut。

    (4)图层是即将包含一个变换动画。则识别动作的键为kCATransition。

    动作对象设置给图层才产生效果

    当一个适当的事件发生在图层上,图层调用它的actionForKey:方法搜索与键关联的动作对象

    Core Animation以下面的顺序搜索动作对象:

    (1)如果图层有一个代理,并且代理实现了actionForLayer:forKey:方法,图层调用该方法。代理必须完成下面所述操作之一:

    <1> 返回给定的键指定的动作对象

    <2> 如果代理不处理动作则返回nil,而搜索操作将继续。

    <3> 返回NSNull对象,这将引起搜索操作立即结束。

    (2)图层在图层的action字典内搜索给定的键

    (3)图层在style字典中查询一个包含键的动作字典。(换句话说,style字典包含一个actions键,它的值也是字典。图层在第二个字典中搜索给定的键。)

    (4)图层调用它的defaultActionForKey:类方法。

    (5)图层执行由Core Animation定义的隐式动作(如果有)。

    当它找到了一个动作对象,图层调用对象的runActionForKey:object:arguments:方法执行动作。

    设置 动作对象的位置 依赖于你打算 如何更改图层。

    (1)对于只应用在指定环境的动作,或对于已经使用代理对象的图层,提供一个代理和实现它的actionForLayer:forKey:方法。

    (2)对于不使用代理的图层对象,添加动作到图层的actions字典。

    (3)与定义在图层对象上的自定义属性相关的动作,包括动作在图层的style字典。

    (4)对于那些是图层行为基础的动作,子类化图层并覆盖defaultActionForKey:方法。

    使用CATransaction类临时禁用动作

    通过创建一个显示事务并设置它的kCATransactionDisableActions属性为True禁用隐式动画。


    提升动画的性能

    Core Animation是提升based-app动画帧率的最佳方式 ,但使用Core Animation并不保证性能一定会得到提升。

    常规的技巧和窍门


    尽可能使用不透明图层

    设置opaque = YES可以让CA知道不需要给图层维持alpha通道,没有alpha通道意味着就不需要渲染这层的背景内容了,从而节省了渲染时间。然后这个属性主要是用于设置或者以层为基础的视图的,也或者是用于核心动画创造的底层bitmap层的情况。如果把一张图像直接设置为层的contents属性,那么这个图像的alpha通道会被强制保留,无论你设不设定这个值。


    将复杂路径拆分成简单路径

    CAShapeLayer类根据你提供的路径来渲染到bitmap图像,在合成的时候渲染成内容。这么做的优点是层总是在最佳分辨率绘制路径,但是这个优点会消耗额外的渲染时间。如果这个路径太复杂,渲染的代价就会很高,并且如果这个路径的尺寸经常改变(这会导致重绘也经常发生),用于绘画的时间也会增加,这会成为一个阻止最佳表现性能的瓶颈

    有一个办法去降低绘制形状层的时间,就是把复杂的形状分拆成简单的形状。用更简单的路径和多层用于CAShapeLayer对象,这比绘制一个大的复杂路径时间快得多。因为绘制操作发生在CPU合成工作发生在GPU,当然这种优化也取决于你的内容。因此,优化前以现有效果为基准很重要。

    显式为相同的图层设置contents属性  --  图层会缓存

    如果你在多个层对象上使用同一张图片,自己加载图像,把这个图像直接分派给这些层对象的contents属性。分配一个图像到contents属性可以预防分配用于内容储备的内存空间(UIView实际并不将自己绘制到屏幕上,而是先绘制到它的图层上,然后是图层显示在屏幕上,视图并不会频繁的重绘;相反,它的绘图结果会被缓存起来,而绘图的缓存版本(后备存储)将被用到适当的地方)。反而这个层用你提供的图像当做后备存储。当几个层用同样的图片,那么这些层就在共享一份内存而不是为自己再分配一个图片拷贝。

    UIView -> 图层 -> 屏幕上

    总是将图层的尺寸设置为整数值

    如果需要,可以使用异步的方式渲染图层

    任何在代理方法drawLayer:inContext或视图的drawRect:方法中的绘制操作都默认是和主线程是同步的,在某种情况下,同步的绘制你的内容可能不会有最好的效果和表现。如果注意到动画执行的不好,可能就得试试drawsAsynchronously这个层的属性(iOS 6引入),让这些操作在后台线程中工作。如果你这么做了,得确定绘制代码是线程安全的,而且理所应当你应该在将异步绘图的代码置入你的产品代码之前总是测试异步绘图的性能。


    当给图层添加一个阴影指定一个阴影路径

    让Core Animation自己决定阴影的形状是个大的开销且影响app的表现。相比让它自己决定,应该用shadowPath属性明确地指定一个阴影形状。当你这么干的时候,核心动画用这个形状去绘制和缓存阴影特效。对那些从不改变或者很少改变形状的层,这是一个很好的效果提升通过减少渲染数量。


    图层样式属性动画


    几何属性

    bounds

    position

    frame(根据bounds和position计算得出,该属性不是一个可动画属性)

    anchorPoint

    cornerRadius

    transform

    zPosition

    背景属性

    Core Animation首先会渲染图层的背景。

    backgroundColor

    图层内容

    如果图层有任何的内容,该内容将被渲染在背景颜色的上面。你可以通过<1>直接设置一副位图提供图层内容,或使用<2>一个代理指定内容,或是<3>子类化图层并直接绘制内容。

    带有圆角半径的图层不会自动裁剪它们的内容;然而,设置图层的masksToBounds = YES将引起图层裁减掉圆角以外的内容

    contents

    contentsGravity

    masksToBounds

    子图层的内容

    sublayers

    lmasksToBounds

    lsublayerTransform


    边框属性

    borderColor

    lborderWidth


    滤镜属性  --  在iOS中,图层忽略任何你赋值给他的滤镜值

    阴影属性

    可以配置阴影的形状、透明度、偏移、模糊半径。

    hadowColor

    lshadowOffset

    lshadowOpacity

    lshadowRadius

    lshaodwPath

    不透明度属性  --  opacity


    蒙版属性  --  mask

    你可以使用一个蒙版遮蔽所有或部分图层内容。蒙版本身是一个图层对象,它的alpha通道被用于决定被遮蔽的内容和被透射的内容。


    可动画属性

    CALayer可动画属性


    键值编码扩展

    Core Animation扩展了NSKeyValueCoding协议,因为它与CAAnimation、CALayer有关。扩展包括为一些键添加了默认的值、扩展了包装转换,并加入了对CGPoint、CGRect、CGSize和CATransform3D类型的键路径支持。

    键值编码适应的容器类

    CAAnimation和CALayer是键值编码适应的容器类

    支持的默认值

    依靠一个类为没有设置值的键提供一个默认值,Core Animation为键值编码加入了一层转换操作。CAAnimation和CALayer类支持这层转换,你可以使用defaultValueForKey:类方法。

    包装转换

    当键的值的数据类型是一个标量或C语言的结构体,你必须在将值赋值到图层之前将值包装成对象

    CGPoint,CGSize,CGRect,CGTransform3D -> NSValue


    键路径对结构体的支持


    CAAnimation和CALayer类可以使用键路径(KeyPath)访问已选择的结构体域。

    CATransform3D键路径

    transform.rotation.z的键路径。

    rotation + scale + translation.x.y.z

    [myLayer setValue:[NSNumber numberWithFloat:10.0] forKeyPath:@”transform.translation.x”];

    CGPoint键路径  --  position.x.y

    CGSize键路径  --  .width.height

    CGRect键路径  --  bounds.size.width

    orign.x.y,size.width.height

    相关文章

      网友评论

          本文标题:Core Animation编程指南

          本文链接:https://www.haomeiwen.com/subject/qnrckttx.html