通过前几篇博客的介绍,我们可以了解到layer层可以设置许多与控件ui相关的属性,并且对于ios开发,uiview层的属性是会映射到calayer的,因此,可以通过uikit和coreanimation两个框架来设置控件的ui相关属性,当属性发生变化时,我们可以使其展示一个动画效果。
caanimation是coreanimation框架中执行动画对象的基类,下面有一张图,是我手画的,不太美观,但是可以将与caanimation相关的几个动画类的关系表达清楚:
从上图中可以看到,从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<nsnumber *> *keytimes;</code>
<code>//每一帧执行过程中的时序效果 上面有提过</code>
<code>@property(nullable, copy) nsarray<camediatimingfunction *> *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<caanimation *> *animations;</code>
<code></code>