CAAnimation是什么?
CAAnimation 是一个抽象动画类。 遵循并实现实现了 CAMediaTiming 和 CAAciotn 两个协议。 CAAnimation 无法直接使用,想要为 Core Animation 的图层或 Scene Kit 对象设置动画,应该使用其子类 CABasicAnimation
,CAKeyframeAnimation
,CAAnimationGroup
或CATransition
的实例。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 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 // 状态的增量
这三个值不能全为空,因为这样你就一个状态也没有指定。
也不能全不为空,因为这样你就指定了三个状态,系统也不知道选哪两个。
若果你指定了一个状态,那系统将自动以当前状态作为另一个状态。
若你指定了两个状态,则系统以这两个状态作为始末状态。
一般情况下,使用 fromValue
和 toValue
即可。
-
使用示例:移动一个视图
// …… 省略了视图部分
// 创建一个动画,针对视图位置 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 // 存放并发执行的所有动画数组
注:
- 动画组中的动画不会被压缩,超出动画时长的部分将会被剪掉
- 动画组中的动画的
delegate
与removedOnCompletion
属性将会被忽略 由于忽略了removedOnCompletion
属性,动画结束图层会恢复到动画前的状态 -
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 针对的是图层而非视图,因此默认情况下,它在完成动画后恢复到最初状态,且不会改变视图的相关属性。
拓展阅读
iOS 动画篇 - Core Animation
iOS 动画篇 - UIKit动画(一)
iOS 动画篇 - UIKit动画(二)
iOS 动画篇 - pop动画库