iOS 动画篇 - CAAnimation初识

CAAnimation是什么?

CAAnimation 是一个抽象动画类。 遵循并实现实现了 CAMediaTiming 和 CAAciotn 两个协议。 CAAnimation 无法直接使用,想要为 Core Animation 的图层或 Scene Kit 对象设置动画,应该使用其子类 CABasicAnimationCAKeyframeAnimationCAAnimationGroupCATransition 的实例。Core Animation可以用在 Mac OS X 和 iOS 平台。Core Animation 的动画执行过程都是在后台操作的,不会阻塞主线程。

注: 要注意的是,Core Animation是直接作用在图层上的,即 CALayer ,并非视图 UIView。当动画之行完毕,视图的 frame 并没有真实地改变。

认识 CAAnimation

  • CAAnimation 类中的常用属性,这些是有关动画效果的几个属性。
// 动画的节奏
@property(nullable, strong) CAMediaTimingFunction *timingFunction;
/*
系统给出的几种类型
 - kCAMediaTimingFunctionLinear //线性节奏,就是匀速
 - kCAMediaTimingFunctionEaseIn //淡入,缓慢加速进入,然后匀速
 - kCAMediaTimingFunctionEaseOut //淡出,匀速,然后缓慢减速移除
 - kCAMediaTimingFunctionEaseInEaseOut //淡入淡出,结合以上两者
 - kCAMediaTimingFunctionDefault //默认效果
*/

// 动画代理,注意该代理使用的是strong,注意释放问题
@property(nullable, strong) id <CAAnimationDelegate> delegate;
// 开始和结束的代理
// 开始
-(void)animationDidStart:(CAAnimation *)anim;
// 结束、flag表示动画正常结束还是被打断移除
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;

// 是否在播放完成后移除,配合 fillMode = kCAFillModeForwards 可以保留最终的播放效果
@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;
  • CAMediaTiming 协议的定义的属性

该协议有关于动画时间相关的,例如开始结束的时间、重复时间等。

@property CFTimeInterval beginTime; // 动画开始时间(滞后时间)
@property CFTimeInterval duration; // 动画持续时间
@property float speed; // 速度 例:如果speed是2,duration是3,那么经过1.5秒,动画播放完成。
@property CFTimeInterval timeOffset; // 动画开始播放偏移时刻
@property float repeatCount; // 重复次数
@property CFTimeInterval repeatDuration; // 重复时间
@property BOOL autoreverses; // 自动执行相反动画
@property(copy) NSString *fillMode; // 播放结束后的状态
  • 使用步骤

1、初始化一个CAAnimation子类对象,设置一些动画相关属性;
2、通过调用CALayer的-addAnimation:forKey:方法增加CAAnimation对象到CALayer上
3、通过调用CALayer的-removeAnimationForKey:方法可以停止CALayer中的动画。

注:一个动画对象可以作用于多个视图,无需多次创建实例。

CABasicAnimation 基础动画

CABasicAnimation 可以看作是特殊的 CAKeyframeAnimation 动画,因为只需要指定一个初始状态和一个终止状态即可。

CABasicAnimation 是 CAPropertyAnimation 的子类,也叫属性动画,也就是针对视图的图层中的可动画属性进行动画操作,例如图层的位置 position、透明度 opacity 等,不是所有的属性都是可以进行动画的。

动画状态解析:

fromValue // 初始状态,即动画开始的状态点
toValue // 终止状态,即动画终止的状态点
byValue // 状态的增量

这三个值不能全为空,因为这样你就一个状态也没有指定。
也不能全不为空,因为这样你就指定了三个状态,系统也不知道选哪两个。
若果你指定了一个状态,那系统将自动以当前状态作为另一个状态。
若你指定了两个状态,则系统以这两个状态作为始末状态。
一般情况下,使用 fromValuetoValue 即可。

  • 使用示例:移动一个视图


    这里写图片描述
// …… 省略了视图部分
// 创建一个动画,针对视图位置 position 进行动画效果
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.duration = 1.0f; //动画时间
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)]; //移动到新的位置
animation.beginTime = CACurrentMediaTime() + 0; //动画开始的时间
animation.autoreverses = YES; //动画结束时是否执行逆动画
animation.repeatCount = HUGE_VALF; //重复次数(无限大)
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; //速率
// animation.removedOnCompletion = NO;
// animation.fillMode = kCAFillModeForwards;
[testView.layer addAnimation:animation forKey:@"animation"]; //将动画添加到layer上
  • 可动画的属性一览

初始化中的 animationWithKeyPath 参数表示 layer 可进行动画的属性,一般常用的属性有以下多种。

KeyPath 说明 样例
transform.scale 缩放 @(0.5)
transform.scale.x 宽的比例 @(0.5)
transform.scale.y 宽的比例 @(0.5)
opacity 透明度 @(0.5)
cornerRadius 圆角 @(0.5)
transform.rotation.x 围绕x轴旋转 @(M_PI)
transform.rotation.y 围绕y轴旋转 @(M_PI)
transform.rotation.z 围绕z轴旋转 @(M_PI)
strokeStart 结合CAShapeLayer使用 赋值多变
strokeEnd 结合CAShapeLayer使用 赋值多变
bounds 大小,中心不变 [NSValue valueWithCGRect:CGRectMake(0, 0, 100, 100)]
position 位置中心点 [NSValue valueWithCGRect:CGPointMake(100, 100)]
contents 显示的内容 (id)[UIImage imageNamed:@”imageName”].CGImage
  • 动画状态的监听

如果需要在动画执行的开始或者结束做点什么的时候,可以设置动画代理来完成状态监听。

- (void)animationDidStart:(CAAnimation *)anim{
    NSLog(@"动画开始");
}
// flag表明了动画是自然结束还是被打断,比如调用了removeAnimationForKey:方法,flag为NO,如果是正常结束,flag为YES。
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
    NSLog(@"%@",flag?@"自然结束":@"被系统或者人为结束");
}

注:此代理是 strong 强引用类型,需要手动置成 nil

CAKeyframeAnimation 关键帧动画

CAKeyframeAnimation 跟 CABasicAnimation 的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue)。而 CAKeyframeAnimation 可以使用状态数组(关键帧数组)来展示不同的运动情况。

简单理解,CABasicAnimation 是针对两个状态的变化,CAKeyframeAnimation 是针对一组状态的变化。

CAKeyframeAnimation 是 CAPropertyAnimation 的子类,同样也是属性动画。

动画状态解析:

values //NSArray对象,里面的元素称为“关键帧” (keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧
path //让图层根据路径移动。Path只对CALayer的anchorPoint和position其作用。如果你设置了path,那么values将被忽略
keyTimes //对应的关键帧制定对应的时间点数组。其取值范围为0到1.0。如果没有设置,则关键帧平分duration
timingFunctions //对应关键帧制定对应的速率。

使用示例:


这里写图片描述
// …… 省略layer部分
// 创建一个关键帧动画
CAKeyframeAnimation *aniByValues = [CAKeyframeAnimation animationWithKeyPath:@"position"];
aniByValues.duration = 3.0f;
aniByValues.repeatCount = HUGE_VALF;
// 设置关键帧位置数组
aniByValues.values = @[[NSValue valueWithCGPoint:testLayer.position],[NSValue valueWithCGPoint:CGPointMake(kScreenWidth-30, testLayer.frame.origin.y)],[NSValue valueWithCGPoint:CGPointMake(kScreenWidth-30, testLayer.frame.origin.y+100)],[NSValue valueWithCGPoint:CGPointMake(30, testLayer.frame.origin.y+100)],[NSValue valueWithCGPoint:testLayer.position],];
// 将动画添加图层上
[testLayer addAnimation:aniByValues forKey:@"position"];

CAAnimationGroup 动画组

可以保存一组动画对象,将 CAAnimationGroup 对象添加到图层上后,组中所有动画对象可以同时并发运行。

CAAnimationGroup 是 CAAnimation 的子类。

属性解析:

animations // 存放并发执行的所有动画数组

注:

  1. 动画组中的动画不会被压缩,超出动画时长的部分将会被剪掉
  2. 动画组中的动画的 delegateremovedOnCompletion 属性将会被忽略 由于忽略了 removedOnCompletion 属性,动画结束图层会恢复到动画前的状态
  3. animations 存放并发执行的所有动画数组元素为CAAnimation的子类

CATransition 转场动画

CAAnimation 的子类,用于做转场动画,能够为图层提供移出屏幕和移入屏幕的动画效果。iOS 比 Mac OS X 的转场动画效果少一点。UINavigationController就是通过CATransition 实现了将控制器的视图推入屏幕的动画效果。

属性解析:

type //动画过渡类型:fade、moveIn、push、reveal。 默认fade
/*
  kCATransitionFade //交叉淡化过渡(不支持过渡方向)
  kCATransitionMoveIn //新视图移到旧视图上面 
  kCATransitionPush //新视图把旧视图推出去
  kCATransitionReveal //将旧视图移开,显示下面的新视图
*/
subtype //动画过渡方向
/* 过渡方向
  kCATransitionFromRight 
  kCATransitionFromLeft
  kCATransitionFromBottom 
  kCATransitionFromTop
*/
startProgress //动画起点(在整体动画的百分比)
endProgress //动画终点(在整体动画的百分比)

转场动画 type,除了系统给定的四种,还有私有的动画可以使用,不过只能使用字符串来设置。

  • cube //立方体翻滚效果
  • oglFlip //上下左右翻转效果
  • suckEffect //收缩效果,如一块布被抽走(不支持过渡方向)
  • rippleEffect //滴水效果(不支持过渡方向)
  • pageCurl //向上翻页效果
  • pageUnCurl //向下翻页效果
  • cameraIrisHollowOpen //相机镜头打开效果(不支持过渡方向)
  • cameraIrisHollowClose //相机镜头关上效果(不支持过渡方向)

使用示例


动画效果
CATransition *transition = [CATransition animation];
transition.type = @"cube"; // 动画过渡类型
transition.subtype = kCATransitionFromRight; // 动画过渡方向
transition.duration = 1; // 动画持续1s
[self.imageView.layer addAnimation:transition forKey:@"KCATransitionAnimation"];

使用场景:imageView切换图片,控制器的 push 或 modal 方法等。

CASpringAnimation 弹性动画

CASpringAnimation 是 CABasicAnimation 基本动画的子类,在 iOS9 之后引入,可以实现弹性动画,例如篮球掉落,弹簧收缩。
CASpringAnimation 动画引入物理引擎,通过设置质量,阻尼系数等值模拟物体的弹性效果。

属性解析:

mass //质量,影响惯性、拉伸幅度
stiffness //刚度系数,刚度系数越大,形变产生的力就越大,运动越快
damping //阻尼系数,阻止弹簧伸缩的系数,阻尼系数越大,停止越快
CGFloat initialVelocity //初始速率  
settlingDuration //结算时间,可根据当前的动画参数估算弹簧动画到停止时的估算时间

使用示例


小球落地效果
CASpringAnimationa *animation = [CASpringAnimation animationWithKeyPath:@"position.y"];
animation.damping = 5;                 // 阻尼系数
animation.stiffness = 100;             // 刚度系数
animation.mass = 1;                    // 质量
animation.initialVelocity = 0;         // 初始速率
animation.duration = animation.settlingDuration;  //结束时间
animation.fromValue = @(self.layer.position.y);
animation.toValue = @(self.layer.position.y+100);
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;

Demo地址

总结

CAAnimation 是一个抽象动画类,无法直接使用,需要使用它的子类,动画分为两大类:属性动画和转场动画。属性动画顾名思义,针对图层可动画属性进行动画,转场动画通常用于视图切换,例如A视图切换为B视图。CAAnimation 针对的是图层而非视图,因此默认情况下,它在完成动画后恢复到最初状态,且不会改变视图的相关属性。

拓展阅读

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

推荐阅读更多精彩内容