天天看点

iOS开发CoreAnimation解读之四——Layer层动画内容

        通过前几篇博客的介绍,我们可以了解到layer层可以设置许多与控件ui相关的属性,并且对于ios开发,uiview层的属性是会映射到calayer的,因此,可以通过uikit和coreanimation两个框架来设置控件的ui相关属性,当属性发生变化时,我们可以使其展示一个动画效果。

        caanimation是coreanimation框架中执行动画对象的基类,下面有一张图,是我手画的,不太美观,但是可以将与caanimation相关的几个动画类的关系表达清楚:

iOS开发CoreAnimation解读之四——Layer层动画内容

从上图中可以看到,从caanimation中继承出三个子类,分别是用于创建属性动画的capropertyanimation,创建转场动画的catransition和创建组合动画的caanimationgroup。

我们就先从根类开始探讨。

caanimation作为动画对象的基类,其中封装了动画的基础属性,如下:

<a href="http://my.oschina.net/u/2340880/blog/539599#">?</a>

1

2

3

4

5

6

7

8

<code>//通过类方法创建一个caanimation对象</code>

<code>+ (instancetype)animation;</code>

<code>//动画执行的时序模式</code>

<code>@property(nullable, strong) camediatimingfunction *timingfunction;</code>

<code>//代理</code>

<code>@property(nullable, strong) id delegate;</code>

<code>//是否动画完成时将动画对象移除掉</code>

<code>@property(getter=isremovedoncompletion) </code><code>bool</code> <code>removedoncompletion;</code>

timingfunction定义了动画执行的时序效果,camediatimingfunction的创建方式如下:

9

10

11

12

13

14

<code>/*</code>

<code>name参数决定的执行的效果,可选参数如下</code>

<code>//线性执行</code>

<code> </code><code>nsstring * const kcamediatimingfunctionlinear;</code>

<code> </code><code>//淡入  在动画开始时 淡入效果</code>

<code> </code><code>nsstring * const kcamediatimingfunctioneasein;</code>

<code> </code><code>//淡出 在动画结束时 淡出效果</code>

<code> </code><code>nsstring * const kcamediatimingfunctioneaseout;</code>

<code> </code><code>//淡入淡出</code>

<code> </code><code>nsstring * const kcamediatimingfunctioneaseineaseout;</code>

<code> </code><code>//默认效果</code>

<code> </code><code>nsstring * const kcamediatimingfunctiondefault;</code>

<code>*/</code>

<code>+ (instancetype)functionwithname:(nsstring *)name;</code>

caanimation的代理方法入如下几个:

<code>//动画开始时执行的回调</code>

<code>- (</code><code>void</code><code>)animationdidstart:(caanimation *)anim;</code>

<code>//动画结束后执行的回调</code>

<code>- (</code><code>void</code><code>)animationdidstop:(caanimation *)anim finished:(</code><code>bool</code><code>)flag;</code>

        capropertyanimation是继承于caanimation专门用来创建与属性相关的动画的类:

<code>//创建对象 参数中的path就是我们要执行动画的属性</code>

<code>//例如,如果传入@"backgroundcolor" 当layer的背景颜色改变时,就会执行我们设置的动画</code>

<code>+ (instancetype)animationwithkeypath:(nullable nsstring *)path;</code>

<code>//这个属性确定动画执行的状态是否叠加在控件的原状态上</code>

<code>//默认设置为no,如果我们执行两次位置移动的动画,会从同一位置执行两次</code>

<code>//如果设置为yes,则会在第一次执行的基础上执行第二次动画</code>

<code>@property(getter=isadditive) </code><code>bool</code> <code>additive;</code>

<code>//这个属性对重复执行的动画有效果</code>

<code>//默认为no,重复执行的动画每次都是从起始状态开始</code>

<code>//如果设置为yes,则为此执行都会在上一次执行的基础上执行</code>

<code>@property(getter=iscumulative) </code><code>bool</code> <code>cumulative;</code>

<code>//这个属性和transfron属性的动画执行相关</code>

<code>@property(nullable, strong) cavaluefunction *valuefunction;</code>

上面这些属性中,只有一个需要我们注意,valuefunction是专门为了transform动画而设置的,因为我们没有办法直接改变transform3d中的属性,通过这个参数,可以帮助我们直接操作transfrom3d属性变化产生动画效果,举例如下,一个绕z轴旋转的动画:

<code> </code><code>//绕z轴旋转的动画</code>

<code>    </code><code>cabasicanimation * ani = [cabasicanimation animationwithkeypath:@</code><code>"transform"</code><code>];</code>

<code>    </code><code>//从0度开始</code>

<code>    </code><code>ani.fromvalue = @0;</code>

<code>    </code><code>//旋转到180度</code>

<code>    </code><code>ani.tovalue = [nsnumber numberwithfloat:m_pi];</code>

<code>    </code><code>//时间2s</code>

<code>    </code><code>ani.duration = 2;</code>

<code>    </code><code>//设置为z轴旋转</code>

<code>    </code><code>ani.valuefunction = [cavaluefunction functionwithname:kcavaluefunctionrotatez];</code>

<code>    </code><code>//执行动画</code>

<code>    </code><code>[layer addanimation:ani forkey:@</code><code>""</code><code>];</code>

实际上,使用点的方式也是可以访问到相应属性的,如果不设置valuefunction,使用如下方法也是可以进行绕z轴旋转的:

<code>//绕z轴旋转的动画</code>

<code>    </code><code>cabasicanimation * ani = [cabasicanimation animationwithkeypath:@</code><code>"transform.rotation.z"</code><code>];</code>

        cabasicanimaton是capropertyanimation分出来的一个子类,创建基础的属性变化动画,例如我们上面的示例代码,其中属性如下:

<code>@property(nullable, strong) id fromvalue;</code>

<code>@property(nullable, strong) id tovalue;</code>

<code>@property(nullable, strong) id byvalue;</code>

上面三个属性都是来确定动画的起始与结束位置,有如下的含义:

fromvalue和tovalue不为空:动画的值由fromvalue变化到tovalue

fromvalue和byvalue不为空:动画的值由fromvalue变化到fromvalue+byvalue

byvalue和tovalue不为空:动画的值由tovalue-byvalue变化到tovalue

只有fromvalue不为空:动画的值由fromvalue变化到layer的当前状态值

只有tovalue不为空:动画的值由layer当前的值变化到tovalue

只有byvalue不为空:动画的值由layer当前的值变化到layer当前的值+byvalue

        cakeyframeanimation也是继承与capropertyanimation的一个子类,其与cabasicanimation的不同之处在于虽然其都是改变layer层属性的动画,但是cabasicanimation只能设置初始与结束状态,这之间我们没办法控制,而cakeyframeanimation可以让我们设置一些关键帧再整个动画的过程中。属性方法如下:

15

16

17

<code>//关键帧的值数组 例如我们想让控件沿某个路径移动,这里面存放每个移动的点</code>

<code>@property(nullable, copy) nsarray *values;</code>

<code>//直接设置路径,作用域values类似</code>

<code>@property(nullable) cgpathref path;</code>

<code>//设置每一帧执行的时间长短 这个的取值为0-1,代表占用时间的比例</code>

<code>@property(nullable, copy) nsarray&lt;nsnumber *&gt; *keytimes;</code>

<code>//每一帧执行过程中的时序效果 上面有提过</code>

<code>@property(nullable, copy) nsarray&lt;camediatimingfunction *&gt; *timingfunctions;</code>

<code>设置帧的中间值如何计算</code>

<code> </code><code>nsstring * const kcaanimationlinear;</code>

<code> </code><code>nsstring * const kcaanimationdiscrete;</code>

<code> </code><code>nsstring * const kcaanimationpaced;</code>

<code> </code><code>nsstring * const kcaanimationcubic;</code>

<code> </code><code>nsstring * const kcaanimationcubicpaced;</code>

<code>@property(copy) nsstring *calculationmode;</code>

示例如下:

<code>    </code><code>cakeyframeanimation * ani = [cakeyframeanimation animationwithkeypath:@</code><code>"position"</code><code>];</code>

<code>    </code><code>ani.values = @[[nsvalue valuewithcgpoint:cgpointmake(100, 100)],[nsvalue valuewithcgpoint:cgpointmake(120, 100)],[nsvalue valuewithcgpoint:cgpointmake(120, 200)],[nsvalue valuewithcgpoint:cgpointmake(200, 200)]];</code>

<code>    </code><code>ani.duration = 3;</code>

        通过caspringanimation,可以帮助开发者很轻松的创建出有弹簧效果的动画,主要属性如下:

<code>//这个属性设置弹簧重物的质量 会影响惯性 必须大于0 默认为1</code>

<code>@property cgfloat mass;</code>

<code>//设置弹簧的刚度系数,必须大于0 默认为100  这个越大 则回弹越快</code>

<code>@property cgfloat stiffness;</code>

<code>//阻尼系数 默认为10 必须大于0 这个值越大 回弹的幅度越小</code>

<code>@property cgfloat damping;</code>

<code>//初始速度</code>

<code>@property cgfloat initialvelocity;</code>

<code>//获取动画停下来需要的时间</code>

<code>@property(readonly) cftimeinterval settlingduration;</code>

        catransition和capropertyanimation的不同之处在于当layer层出现时,会产生动画效果,而并不是属性改变时,属性如下:

18

19

20

21

22

23

24

<code>设置动画类型</code>

<code>//淡入</code>

<code> </code><code>nsstring * const kcatransitionfade;</code>

<code> </code><code>//移入</code>

<code> </code><code>nsstring * const kcatransitionmovein;</code>

<code> </code><code>//压入</code>

<code> </code><code>nsstring * const kcatransitionpush;</code>

<code> </code><code>//溶解</code>

<code> </code><code>nsstring * const kcatransitionreveal;</code>

<code>@property(copy) nsstring *type;</code>

<code>设置动画的方向</code>

<code>//从右侧进</code>

<code> </code><code>nsstring * const kcatransitionfromright;</code>

<code> </code><code>//从左侧进</code>

<code> </code><code>nsstring * const kcatransitionfromleft;</code>

<code> </code><code>//从上侧进</code>

<code> </code><code>nsstring * const kcatransitionfromtop;</code>

<code> </code><code>//从下侧进</code>

<code> </code><code>nsstring * const kcatransitionfrombottom;</code>

<code>@property(nullable, copy) nsstring *subtype;</code>

其实,关于type定义的动画效果,出来官方定义的,我们还可以使用一些私有的参数,如下:

<code>pagecurl   翻页</code>

<code>rippleeffect 滴水效果</code>

<code>suckeffect 收缩效果,如一块布被抽走</code>

<code>cube 立方体效果</code>

<code>oglflip 上下翻转效果</code>

例如:

<code>    </code><code>catransition * ani = [catransition animation];</code>

<code>    </code><code>ani.type =  @</code><code>"pagecurl"</code><code>;</code>

<code>    </code><code>ani.subtype = kcatransitionfromright;</code>

        caanimationgroup本身并没有定义动画,他可以将我们上面提到的相关动画进行组合:

<code>@property(nullable, copy) nsarray&lt;caanimation *&gt; *animations;</code>

<code></code>

继续阅读