iOS动画-CAAnimation的说明与简单使用

CAAnimation是QuartzCore框架里面定义的

CAAnimation主要是遵循了 CAMediaTiming 协议,拥有了一些动画的属性

属性 参数类型 备注
beginTime CFTimeInterval 指定动画开始的时间。(设置动画beginTime为1,动画将延时1秒后开始执行)
duration CFTimeInterval 动画时长;(默认值为0,但是实际动画默认持续时间为0.25秒)
speed float 动画执行的速度;(默认值为0,减少它会减慢动画的时间,增加它会加快速度)(设置speed为2时,则动画实际执行时间是duration的一半)
timeOffset CFTimeInterval 动画时间偏移量;(设置时长3秒动画的timeOffset为1时,动画会从1秒位置执到最后,再执行之前跳过的部分)
repeatCount float 重复的次数。不停重复设置为 HUGE_VALF
repeatDuration CFTimeInterval 设置动画的时间。在该时间内动画一直执行,不计次数。
autoreverses BOOL 动画结束时是否执行逆动画 ,动画从初始值执行到最终值,是否会反向回到初始值;(设置为YES,动画完成后将以动画的形式回到初始位置)
fillMode NSStrinng 决定当前对象在非动画时间端段的动画属性值,如动画开始之前和动画结束之后
timingFunction CAMediaTimingFunction 设置动画的速度变化
fromValue id 所改变属性的起始值
toValue id 所改变属性的结束时的值
byValue id 所改变属性相同起始值的改变量
removedOnCompletion BOOL 动画完成之后是否还原,默认为yes。

一些常用的animationWithKeyPath值的总结

使用形式 备注
transform.scale @(0.8) 比例转化,在所有方向上进行缩放
transform.scale.x @(0.8) 宽的比例
transform.scale.y 高的比例 @(0.8)
transform.rotation.x 围绕x轴旋转 @(M_PI)
transform.rotation.y 围绕y轴旋转 @(M_PI)
transform.rotation.z 围绕z轴旋转 @(M_PI)
cornerRadius 圆角的设置 @(50)
backgroundColor 背景颜色的变化 (id)[UIColor grayColor].CGColor
bounds 中心不变,改变大小 [NSValue valueWithCGRect:CGRectMake(0, 0, 50, 50)];
position 中心改变) [NSValue valueWithCGPoint:CGPointMake(300, 300)];
contents 改变内容,比如UIImageView的图片 imageAnima.toValue = (id)[UIImage imageNamed:@"name"].CGImage;
opacity 透明度 @(0.6)
contentsRect.size.width 横向拉伸缩放 @(0.3)最好是0~1之间的
contentsRect.size.height 纵向拉伸缩放 @(0.3)最好是0~1之间的

核心动画Core Animation常用类的继承关系

动画类 动画特性
CAMediaTiming 协议;定义了一段动画内用于控制时间的属性的集合
CAAnimation 抽象类;作为所有动画类型父类,不可直接使用
CAPropertyAnimation 抽象类;作为基础动画和帧动画的父类,不可直接使用
CABasicAnimation 基础动画;用于实现单一属性变化的动画
CAKeyFrameAnimation 关键帧动画;用于实现单一属性连续变化的动画
CAAnimaitionGroup 组动画;用于实现多属性同时变化的动画
CATrasition 转场过渡动画;

CAMediaTiming只有这两个代理方法 顾名思义,一个开始一个结束,CAAnimation实现代理方法不同于其他,CAAnimation不用声明CAAnimationDelegate。直接重写方法即可

/* Delegate methods for CAAnimation. */

@protocol CAAnimationDelegate <NSObject>
@optional

/* Called when the animation begins its active duration. */
//动画的开始的回调
- (void)animationDidStart:(CAAnimation *)anim;

/* Called when the animation either completes its active duration or
 * is removed from the object it is attached to (i.e. the layer). 'flag'
 * is true if the animation reached the end of its active duration
 * without being removed. */
//动画结束的回调 。flag参数表明了动画是自然结束还是被打断的
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;

@end

1.CABasicAnimation
通过设定起始点,终点,时间,动画会沿着你这设定点进行移动。可以看做特殊的CAKeyFrameAnimation
2.CAKeyframeAnimation
Keyframe顾名思义就是关键点的frame,你可以通过设定CALayer的始点、中间关键点、终点的frame,时间,动画会沿你设定的轨迹进行移动
3.CAAnimationGroup
Group也就是组合的意思,就是把对这个Layer的所有动画都组合起来。PS:一个layer设定了很多动画,他们都会同时执行,
4.CATransition
这个就是苹果帮开发者封装好的一些动画,

KeyFrame的意思是关键帧,所谓“关键”就是改变物体运动趋势的帧,在该点处物体将发生运动状态,比如矩形的四个角,抛物线的顶点等。

values 指明整个动画过程中的关键帧点
path 与values属性一样,同样是用于指定整个动画所经过的路径的。需要注意的是,values与path是互斥的,当values与path同时指定时,path会覆盖values,即values属性将被忽略。
keyTimes 是一个数组,用以指定每个子路径(AB,BC,CD)的时间。如果你没有显式地对keyTimes进行设置,则系统会默认每条子路径的时间为:ti=duration/(5-1),即每条子路径的duration相等,都为duration的1\4。当然,我们也可以传个数组让物体快慢结合。例如,你可以传入{0.0, 0.1,0.6,0.7,1.0},其中首尾必须分别是0和1,因此tAB=0.1-0, tCB=0.6-0.1, tDC=0.7-0.6, tED=1-0.7.....
timeFunctions 这个属性用以指定时间函数,类似于运动的加速度,有以下几种类型。记住,这是一个数组,你有几个子路径就应该传入几个元素
/** Timing function names. **/

CA_EXTERN NSString * const kCAMediaTimingFunctionLinear
    CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);//默认,匀速执行动画
CA_EXTERN NSString * const kCAMediaTimingFunctionEaseIn
    CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);//浅入,先慢慢加速,后突然停止
CA_EXTERN NSString * const kCAMediaTimingFunctionEaseOut
    CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);//先全速开始,再慢慢减速停止
CA_EXTERN NSString * const kCAMediaTimingFunctionEaseInEaseOut
    CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);//浅入浅出,先慢慢加速,再慢慢减速
CA_EXTERN NSString * const kCAMediaTimingFunctionDefault
    CA_AVAILABLE_STARTING (10.6, 3.0, 9.0, 2.0);//效果同KCAMediaTimingFuncationEaseInEaseOut

calculationMode 该属性决定了物体在每个子路径下是跳着走还是匀速走,跟timeFunctions属性有点类似

/* `calculationMode' strings. */

CA_EXTERN CAAnimationCalculationMode const kCAAnimationLinear
    API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));//线性,默认
CA_EXTERN CAAnimationCalculationMode const kCAAnimationDiscrete
    API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));//离散,无中间过程,但keyTimes设置的时间依旧生效,物体跳跃的出现在各个关键帧上
CA_EXTERN CAAnimationCalculationMode const kCAAnimationPaced
    API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));//平均,keyTimes和Timing functions设置失效
CA_EXTERN CAAnimationCalculationMode const kCAAnimationCubic
    API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0));//平均,同上
CA_EXTERN CAAnimationCalculationMode const kCAAnimationCubicPaced
    API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0));//平均,同上

/* `rotationMode' strings. */

CA_EXTERN CAAnimationRotationMode const kCAAnimationRotateAuto
    API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
CA_EXTERN CAAnimationRotationMode const kCAAnimationRotateAutoReverse
    API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

示例

实现水波动画

- (void)drawRect:(CGRect)rect {
     //新建动画数组
    CALayer *animationLayer = [CALayer layer];
    CAAnimationGroup *animationGroup = [self animationGroupAnimations:[self animationArray]];
    CALayer *pulsingLayer = [self pulsingLayer:rect animationGroup:animationGroup];
    //将动画 Layer 添加到 animationLayer
    [animationLayer addSublayer:pulsingLayer];
    
    // 新建缩放动画
    CABasicAnimation *animationTwo = [self oppositeScaleAnimation];
    // 新建一个动画 Layer,将动画添加上去
    CALayer *pulsingLayerTwo = [self pulsingLayer:rect animation:animationTwo];
    //将动画 Layer 添加到 animationLayer
    [animationLayer addSublayer:pulsingLayerTwo];
    [self.layer addSublayer:animationLayer];
}

- (CALayer *)pulsingLayer:(CGRect)rect animation:(CABasicAnimation *)animation {
    CALayer *pulsingLayer = [CALayer layer];
    pulsingLayer.borderWidth = 0.5;
    pulsingLayer.borderColor = [[UIColor whiteColor]colorWithAlphaComponent:0.4].CGColor;
    pulsingLayer.frame = CGRectMake(0, 0, rect.size.width, rect.size.height);
    pulsingLayer.cornerRadius = rect.size.height / 2;
    [pulsingLayer addAnimation:animation forKey:@"plulsing"];
    return pulsingLayer;
}

- (CALayer *)pulsingLayer:(CGRect)rect animationGroup:(CAAnimationGroup *)animationGroup {
    CALayer *pulsingLayer = [CALayer layer];
    pulsingLayer.borderWidth = 1;
    pulsingLayer.borderColor = [[UIColor whiteColor]colorWithAlphaComponent:0.4].CGColor;
    pulsingLayer.frame = CGRectMake(0, 0, rect.size.width, rect.size.height);
    pulsingLayer.cornerRadius = rect.size.height / 2;
    [pulsingLayer addAnimation:animationGroup forKey:@"plulsing"];

    return pulsingLayer;
}

- (CAAnimationGroup *)animationGroupAnimations:(NSArray *)array {
    CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
    animationGroup.beginTime = CACurrentMediaTime();
    animationGroup.duration = 2;
    animationGroup.repeatCount = 2;
    animationGroup.autoreverses = YES;//动画结束时是否执行逆动画
    animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];//设置动画的速度变化:淡出
    animationGroup.removedOnCompletion
    return animationGroup;
}


- (NSArray *)animationArray {
    NSArray *animationArray = nil;
    CABasicAnimation *scaleAnimation = [self scaleAnimation];
    CAKeyframeAnimation *borderColorAnimation = [self borderColorAnimation];
    animationArray = @[scaleAnimation, borderColorAnimation];
    return animationArray;
}

- (CABasicAnimation *)scaleAnimation {
    CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
     
    scaleAnimation.fromValue = @1;
    scaleAnimation.toValue = @3;
    return scaleAnimation;
} 

- (CABasicAnimation *)oppositeScaleAnimation {
    CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    scaleAnimation.fromValue = @1;
    scaleAnimation.toValue = @0.7;
    scaleAnimation.beginTime = CACurrentMediaTime();
    scaleAnimation.duration = 2;
    scaleAnimation.repeatCount = 2;
    scaleAnimation.autoreverses = YES;//动画结束时是否执行逆动画
    scaleAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];//设置动画的速度变化:淡出
    return scaleAnimation;
}

- (CAKeyframeAnimation *)borderColorAnimation {
    CAKeyframeAnimation *borderColorAnimation = [CAKeyframeAnimation animation];
    borderColorAnimation.keyPath = @"borderColor";
    borderColorAnimation.values = @[
        (__bridge id)[[UIColor whiteColor]colorWithAlphaComponent:0.4].CGColor,
        (__bridge id)[[UIColor whiteColor]colorWithAlphaComponent:0.3].CGColor,
        (__bridge id)[[UIColor whiteColor]colorWithAlphaComponent:0.2].CGColor,
        (__bridge id)[[UIColor whiteColor]colorWithAlphaComponent:0.1].CGColor,
        (__bridge id)[[UIColor whiteColor]colorWithAlphaComponent:0.0].CGColor];
    borderColorAnimation.keyTimes = @[@0.2,@0.4,@0.6,@0.8,@1
    ];
    return borderColorAnimation;
}

引用、借鉴

iOS动画-CAAnimation使用详解https://www.jianshu.com/p/c22918a5e7ca
简书发表文章格式(MakrDwon使用)https://www.jianshu.com/p/0e63982d7a98

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

推荐阅读更多精彩内容