动画(二) Code Animation 核心动画

 一、核心动画结构及定义

      Code Animation 中文翻译为核心动画,它是一组非常强的的动画处理API,是以它能做出非常炫丽的动画效果,且往往事半功倍

    核心动画所处的位置入下图所示:


Core Animation 结构

      可以看到,Code Animation位于UIKit的下一层,是作用在CALayer(Core Animation layer)上,相较于UIView动画,它可以实现更复杂的动画效果。

    下边我们看一下,核心动画的几个类及结构


Code Animation类及结构

下边分析一下上图结构:

**1.  CAMediaTiming** 协议中定义了时间,速度,重复次数等。属性定义如下:

beginTime -> 用来设置动画延时,若想延迟1秒,就设置为CACurrentMediaTime()+1,其中CACurrentMediaTime()为图层当前时间。

duration -> 动画的持续时间。

speed -> 动画速率,决定动画时间的倍率。当speed为2时,动画时间为设置的duration的1/2。

timeOffset -> 动画时间偏移量。比如设置动画时长为3秒,当设置timeOffset为1.5时,当前动画会从中间位置开始,并在到达指定位置时,走完之前跳过的前半段动画。

repeatCount -> 动画的重复次数。

repeatDuration -> 动画的重复时间。

autoreverses -> 动画由初始值到最终值后,是否反过来回到初始值的动画。如果设置为YES,就意味着动画完成后会以动画的形式回到初始值。

fillMode -> 决定当前对象在非动画时间段的行为.比如动画开始之前,动画结束之后。

(注:其实不只是CAAnimation遵循CAMediaTiming协议,熟悉底层结构的小伙伴们应该知道CALayer也遵循这个协议,所有在一定程度上我们可以通过控制layer本身的协议属性来控制动画节奏。)

**2. CAAnimation** 核心动画基础类,不能直接使用。除了CAMediaTiming协议中的方法,增加了CAAnimationDelegate的代理属性等。具体如下:

timingFunction -> 控制动画的节奏。系统提供的包括:kCAMediaTimingFunctionLinear (匀速),kCAMediaTimingFunctionEaseIn (慢进快出),kCAMediaTimingFunctionEaseOut (快进慢出),kCAMediaTimingFunctionEaseInEaseOut (慢进慢出,中间加速),kCAMediaTimingFunctionDefault (默认),当然也可通过自定义创建CAMediaTimingFunction。

delegate -> 代理。

removedOnCompletion -> 是否让图层保持显示动画执行后的状态,默认为YES,也就是动画执行完毕后从涂层上移除,恢复到执行前的状态,如果设置为NO,并且设置fillMode为kCAFillModeForwards,则保持动画执行后的状态。

**3. CATransition** 转场动画,系统提供了很多酷炫效果。属性如下:

type -> 转场动画类型。

subtype -> 转场动画方向。

startProgress -> 动画起点进度(整体的百分比)。

endProgress -> 动画终点进度(整体的百分比)。

filter -> 自定义转场。

**4.CAPropertyAnimation** 属性动画,针对对象的可动画属性进行效果的设置,不可直接使用。添加属性具体如下:

keyPath -> CALayer的某个属性名,并通过这个属性的值进行修改,达到相应的动画效果。

additive -> 属性动画是否以当前动画效果为基础,默认为NO。

cumulative -> 指定动画是否为累加效果,默认为NO。

valueFunction -> 此属性配合CALayer的transform属性使用。

**5.CABasicAnimation**基础动画,通过keyPath对应属性进行控制,需要设置fromValue以及toValue。添加属性如下:

fromValue -> keyPath相应属性的初始值。

toValue -> keyPath相应属性的结束值。

byValue -> 在不设置toValue时,toValue = fromValue + byValue,也就是在当前的位置上增加多少。

**6.CASpringAnimation** 带有初始速度以及阻尼指数等物理参数的属性动画。我们可以把它看成在不绝对光滑的地面上,一个弹簧拴着别小球,那么我们可以这么理解他的属性(物理知识请问一下牛顿大叔):

mass -> 小球质量,影响惯性。

stiffness -> 弹簧的劲度系数。

damping -> 阻尼系数,地面的摩擦力。

initialVelocity -> 初始速度,相当于给小球一个初始速度(可正可负,方向不同)

settlingDuration -> 结算时间,根据上述参数计算出的预计时间,相对于你设置的时间,这个时间比较准确。

**7.CAKeyframeAnimation** 关键帧动画,同样通过keyPath对应属性进行控制,但它可以通过values或者path进行多个阶段的控制。属性如下:

values -> 关键帧组成的数组,动画会依次显示其中的每一帧。

path -> 关键帧路径,动画进行的要素,优先级比values高,但是只对CALayer的anchorPoint和position起作用。

keyTimes -> 每一帧对应的时间,如果不设置,则各关键帧平分设定时间。

timingFunctions -> 每一帧对应的动画节奏。

calculationMode -> 动画的计算模式,系统提供了对应的几种模式。

tensionValues -> 动画张力控制。

continuityValues -> 动画连续性控制。

biasValues -> 动画偏差率控制。

rotationMode -> 动画沿路径旋转方式,系统提供了两种模式。

**8.CAAnimationGroup** 动画组,方便对于多动画的统一控制管理。

animations -> 所有动画效果元素的数组。

 二 、方法与代码示例

**1、CABasicAnimation**

在一般的应用开发中,基础动画可以满足大部分的开发需求,主要完成对于对象指定动画属性两个Value之间的动画过度。

+(instancetype)animationWithKeyPath:(nullable NSString *)path;

**path:**CALayer的某个属性名,并通过这个属性的值进行修改,达到相应的动画效果。下为可选参数:

>  CATransform3D Key Paths :

> 旋转

> transform.rotation.z

> rotation.x

> rotation.y

> rotation.z

> rotation

>

> 缩放

> scale.x

> scale.y

> scale.z

> scale

>

> 平移

> translation.x

> translation.y

> translation.z

> translation

>

> 位置

> CGPoint Key Paths:position.x

> x

> y

>

> 位置及大小

> CGRect Key Paths :

> bounds.size.width

> origin.x

> origin.y

> origin

> size.width

> size.height

> size

> opacity 透明度

> backgroundColor 背景色

> cornerRadius  圆角

> borderWidth  边距线宽

> contents      内容

>   

> 阴影

> Shadow Key Path:

>  shadowColor

>  shadowOffset

>  shadowOpacity

>  shadowRadius

代码示例:

> -(void)basicAnimationWithTag:(NSInteger)tag{

>    CABasicAnimation *basicAni = nil;

>    switch (tag) {

>        case 0:

>            //初始化动画并设置keyPath

>            basicAni = [CABasicAnimation animationWithKeyPath:@"position"];

>            //到达位置

>            basicAni.byValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)];

>            break;

>        case 1:

>            basicAni = [CABasicAnimation animationWithKeyPath:@"transform.scale"];

>            //到达缩放

>            basicAni.toValue = @(0.1f);

>            break;

>        case 2:

>            basicAni = [CABasicAnimation animationWithKeyPath:@"opacity"];

>            basicAni.toValue=@(0.1f);

>            break;

>        case 3:

>            basicAni = [CABasicAnimation animationWithKeyPath:@"transform"];

>            //3D

>            basicAni.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2+M_PI_4, 1, 1, 0)];

>            break;

>        case 4:

>            basicAni = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];

>            //圆角

>            basicAni.toValue=@(50);

>            break;

>        default:

>            break;

>    }

>    //设置代理

>    basicAni.delegate = self;

>    //延时执行

>    //basicAni.beginTime = CACurrentMediaTime() + 2;

>    //动画时间

>    basicAni.duration = 1;

>    //动画节奏

>    basicAni.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

>    //动画速率

>    //basicAni.speed = 0.1;

>    //图层是否显示执行后的动画执行后的位置以及状态

>    //basicAni.removedOnCompletion = NO;

>    //basicAni.fillMode = kCAFillModeForwards;

>    //动画完成后是否以动画形式回到初始值

>    basicAni.autoreverses = YES;

>    //动画时间偏移

>    //basicAni.timeOffset = 0.5;

>    //添加动画

>    NSString *key = NSStringFromSelector(_cmd);

>    NSLog(@"动画的key ======= %@",key);

>    [_animationLayer addAnimation:basicAni forKey:key];

> }

**2、CASpringAnimation**

CASpringAnimation是iOS9才引入的动画类,效果类似于UIView的spring动画,不过比其增加了质量,劲度系数等属性的扩展,继承于CABaseAnimation,用法也很简单:

>  CASpringAnimation *springAni = [CASpringAnimation animationWithKeyPath:@"position"];

>    springAni.damping = 2;

>    springAni.stiffness = 50;

>    springAni.mass = 1;

>    springAni.initialVelocity = 2;

>    springAni.toValue = [NSValue valueWithCGPoint:CGPointMake(270, 350)];

>    springAni.duration = springAni.settlingDuration;

>    [_animationLayer addAnimation:springAni forKey:@"springAnimation"];

**3.CAKeyframeAnimation**

关键帧动画和CABasicAnimation一样是CApropertyAnimation的子类,但是CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation使用values数组可以通过(keyTimes)设置多个关键帧,同时可以利用path可以进行位置或者锚点的动画操作。代码如下

通过values设置

>  CAKeyframeAnimation *keyFrameAni = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];

> keyFrameAni.duration = 2;

> keyFrameAni.values = @[@(-(6) / 180.0*M_PI),@((6) / 180.0*M_PI),@(-(5) / 180.0*M_PI),@((5) / 180.0*M_PI),@(-(4) / 180.0*M_PI),@((4) / 180.0*M_PI),@(-(4) / 180.0*M_PI)];

> keyFrameAni.keyTimes = @[ @(0), @(0.225), @(0.425), @(0.6), @(0.75), @(0.875), @(1)];

> keyFrameAni.repeatCount = 2;

> [_animationLayer addAnimation:keyFrameAni forKey:@"keyFrameAnimation"];

通过path设置

    CAKeyframeAnimation *keyFrameAni = [CAKeyframeAnimation animationWithKeyPath:@"position"];

    UIBezierPath *path = [UIBezierPath bezierPath];

    [path moveToPoint:_animationLayer.position;

    [path addCurveToPoint:CGPointMake(300, 500) controlPoint1:CGPointMake(100, 400) controlPoint2:CGPointMake(270, 460)];

    keyFrameAni.path = path.CGPath;

    keyFrameAni.duration = 1;

    [_animationLayer addAnimation:keyFrameAni forKey:@"keyFrameAnimation"];

**4.CATransition**

转场动画是一种显示样式向另一种显示样式过渡的效果,能制作出酷炫的效果,不过谨慎使用私有API,防止被拒的悲剧。

>    **type的enum值如下:**

>    kCATransitionFade 渐变

>    kCATransitionMoveIn 覆盖

>    kCATransitionPush 推出

>    kCATransitionReveal 揭开

还有一些私有动画类型,效果很炫酷,不过不推荐使用。


转场动画效果

subtype可取值:

>    **subtype的enum值如下:**

>    kCATransitionFromRight 从右边

>    kCATransitionFromLeft 从左边

>    kCATransitionFromTop 从顶部

>    kCATransitionFromBottom 从底部

代码示例

>      CATransition *transtion = [CATransition animation];

>    transtion.duration = 1;

>    transtion.type = @"cube";

>    transtion.subtype = kCATransitionFromRight;//kCATransitionFromLeft  kCATransitionFromRight

>    _animationLayer.backgroundColor = [UIColor yellowColor].CGColor;

>    [_animationLayer addAnimation:transtion forKey:@"transtion"];

**5.CAAnimationGroup**

CAAnimationGroup 是一个动画组,使用Group可以将多个动画合并一起加入到层中,Group中所有动画并发执行,可以方便地实现需要多种类型动画的场景。

代码示例

    //弹动动画

    CAKeyframeAnimation *keyFrameAni = [CAKeyframeAnimation animationWithKeyPath:@"position.y"];

    CGFloat ty = _animationLayer.position.y;

    keyFrameAni.values = @[@(ty - 100),@(ty),@(ty - 50),@(ty)];

    //每一个动画可以单独设置时间和重复次数,在动画组的时间基础上,控制单动画的效果

    keyFrameAni.duration = 0.3;

    keyFrameAni.repeatCount= MAXFLOAT;

    keyFrameAni.delegate = self;

    //

    //圆角动画

    CABasicAnimation *basicAni = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];

    //到达位置

    basicAni.byValue = @(_animationLayer.bounds.size.width/2);

    //

    basicAni.duration = 1;

    basicAni.repeatCount = 1;

    //

    basicAni.removedOnCompletion = NO;

    basicAni.fillMode = kCAFillModeForwards;

    //设置代理

    basicAni.delegate = self;

    //动画时间

    basicAni.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

    CAAnimationGroup *aniGroup = [CAAnimationGroup animation];

    aniGroup.animations = @[keyFrameAni,basicAni];

    aniGroup.autoreverses = YES;

    //动画的表现时间和重复次数由动画组设置的决定

    aniGroup.duration = 3;

    aniGroup.repeatCount=MAXFLOAT;

    //

    [_animationLayer addAnimation:aniGroup forKey:@"groupAnimation"];


三、动画的暂停、恢复、加快及移除动画

1、speed属性是指当前层动画的速率。用于将父时间缩放到本地时间,例如。

如果速率为2,则本地时间的进展速度是父时间的两倍。

我们可以通过设置speed =0来暂停动画:

代码示例:

 //获取当前layer的动画媒体时间

    CFTimeInterval interval = [_animationLayer convertTime:CACurrentMediaTime() toLayer:nil];

    //设置时间偏移量,保证停留在当前位置

    _animationLayer.timeOffset= interval;

    //暂定动画

    _animationLayer.speed = 0;

设置speed =1来恢复动画

代码示例:

 //获取暂停的时间

    CFTimeInterval beginTime = CACurrentMediaTime() - _animationLayer.timeOffset;

    //设置偏移量

    _animationLayer.timeOffset = 0;

    //设置开始时间

    _animationLayer.beginTime= beginTime;

    //开始动画

    _animationLayer.speed = 1;

设置speed >1来加速动画

代码示例:

 _animationLayer.speed = 2;


2、动画结束,我们可以移除动画

[_animationLayer removeAllAnimations];//移除当前层所有动画

    //[_animationLayer removeAnimationForKey:@"groupAnimation"];//移除当前层上名称是groupAnimation的动画

  关于Code Animation ,就写到这里了,附demo一份GitHub - Tony-iOS-Personal/AnimationDemo: 关于动画的总结demo

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容