文章目录
- 简介
- CAAnimation类
- CAMediaTiming协议常用属性
- CAAnimation类的代理协议CAAnimationDelegate
- 动画实现步骤
- 举例:
- CAPropertyAnimiation类
- CABasicAnimation
- 举例
- CASpringAnimation 弹簧动画
- CAKeyFrameAnimation
- 举例
- CAAnimationGroup动画组
- CATransition转场动画
- 例子
- 代码
CoreAnimation框架是苹果的核心技术之一,iOS以及MacOS之所以大受欢迎,其中一个重要的原因在于能够提供非常炫酷的动画效果,同时其对硬件的要求很低。
简介
Core Animation,中文翻译为核心动画,使用少量的代码就可以实现非常强大的功能。Core Animation的动画执行过程都是在后台操作的,因此不会阻塞主线程。
核心动画是直接作用于CALayer对象上的。当我们对一个UIView视图对象显示的内容进行旋转操作时,其本质是修改UIView的layer属性,对layer所展示的样式进行旋转操作后,再渲染到屏幕上。
CAAnimation类
CAAnimation类是一个抽象类,因此我们不会直接创建CAAnimation类的对象,而是使用其子类对象。其有3个子类,分别为:
- CAPropertyAnimiation属性动画
- CAAnimationGroup动画组
- CATransition转场动画
其中,CAPropertyAnimiation属性动画又包含两个子类,分别为: - CABasicAnimation基本动画
- CAKeyframeAnimation关键帧动画
在iOS9发布后,CABasicAnimation基本动画又添加了一个子类CASpringAnimation弹簧动画。
CAMediaTiming协议常用属性
CAAnimation类遵守了CAMediaTiming协议,在该协议中定义了一些常用的与动画播放相关的属性。常用的包括如下几个。
beginTime:动画开始播放的时间,默认为0,即立即开始播放
@property CFTimeInterval beginTime;
duration:动画持续的时间,默认为0
@property CFTimeInterval duration;
speed:动画播放的速度,默认为1,数值越大播放的速度越快,例如,当取值为2时,以两倍速度播放动画
@property float speed;
repeatCount:动画重复播放的次数
@property float repeatCount;
repeatDuration:动画重复播放的时间间隔
@property CFTimeInterval repeatDuration;
fillMode:定义动画播放完毕后的动作,一共有4个可选动作,默认为:kCAFillModeRemoved,即恢复原样
@property(copy) NSString *fillMode;
CA_EXTERN NSString * const kCAFillModeForwards;
CA_EXTERN NSString * const kCAFillModeBackwards;
CA_EXTERN NSString * const kCAFillModeBoth;
CA_EXTERN NSString * const kCAFillModeRemoved;
CAAnimation类的代理协议CAAnimationDelegate
CAAnimationDelegate是CAAnimation类的代理协议,其中定义了与动画播放相关的一些方法,主要包括:
动画开始播放时调用的方法
- (void)animationDidStart:(CAAnimation *)anim;
动画停止播放时调用的方法,停止播放的原因有可能是动画播放完成,也有可能是人为控制动画停止播放
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
动画实现步骤
当我们需要创建一个动画时,通常可以按照如下步骤进行:
实例化一个CAAnimation的子类对象,例如CABasicAnimation、CAKeyframeAnimation、CATransition等;
设置动画对象的动画属性;
添加动画对象到一个CALayer类的对象上,并播放动画。
举例:
我们通过一个简单的示例,介绍一下动画的实现步骤,该示例实现了对一个视图对象的layer进行平移,在平移的过程中播放动画。
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//初始化CALayer对象,并添加到控制器view的layer上
CALayer *subLayer = [CALayer layer];
subLayer.frame = CGRectMake(140, 100, 100, 100);
subLayer.backgroundColor = [UIColor yellowColor].CGColor;
subLayer.borderColor = [UIColor redColor].CGColor;
subLayer.borderWidth = 4.0;
subLayer.cornerRadius = 2.0;
[self.view.layer addSublayer:subLayer];
//延时1秒后
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//1-实例化CABasicAnimation对象
CABasicAnimation *animation = [CABasicAnimation animation];
//2-设置动画属性
animation.keyPath = @"position";
//锚点
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(290, 150)];
animation.duration = 2.0;
animation.repeatCount=3;
//3-添加动画对象到一个CALayer类的对象上,播放动画
[subLayer addAnimation:animation forKey:nil];
});
}
CAPropertyAnimiation类
CAPropertyAnimiation属性动画类是CAAnimation类的子类,其也是一个抽象类,在实际开发过程中,我们需要使用其子类,包括:CABasicAnimation类、CAKeyFrameAnimation类。在iOS9中,CABasicAnimation类由引入了一个新的子类CASpringAnimation类。
CAPropertyAnimiation类,从其字面意义上理解其与属性Property相关,即修改Property从而把属性变化的过程通过动画展现出来。在CAPropertyAnimiation类中,通过keyPath属性来设置针对哪个属性变化展现动画。
@property(nullable, copy) NSString *keyPath;
常用的keyPath:
// 旋转
transform.rotation.x 围绕x轴翻转 参数:角度 angle2Radian(4)
transform.rotation.y 围绕y轴翻转 参数:同上
transform.rotation.z 围绕z轴翻转 参数:同上
transform.rotation 默认围绕z轴
// 缩放
transform.scale.x x方向缩放 参数:缩放比例 1.5
transform.scale.y y方向缩放 参数:同上
transform.scale.z z方向缩放 参数:同上
transform.scale 所有方向缩放 参数:同上
// 平移
transform.translation.x x方向移动 参数:x轴上的坐标 100
transform.translation.y x方向移动 参数:y轴上的坐标
transform.translation.z x方向移动 参数:z轴上的坐标
transform.translation 移动 参数:移动到的点 (100,100)
// 其他属性
opacity 透明度 参数:透明度 0.5
backgroundColor 背景颜色 参数:颜色 (id)[[UIColor redColor] CGColor]
cornerRadius 圆角 参数:圆角半径 5
borderWidth 边框宽度 参数:边框宽度 5
bounds 大小 参数:CGRect
contents 内容 参数:CGImage
contentsRect 可视内容 参数:CGRect 值是0~1之间的小数
position 锚点位置
shadowColor 阴影颜色
shadowOffset 阴影的偏移量
shadowOpacity 阴影的透明度
shadowRadius 阴影的圆角
CABasicAnimation
CABasicAnimation类是使用最简单的核心动画类,我们只需要指定keyPath,然后设置起始值(fromValue)和目标值(toValue),然后再把该动画对象添加到一个CALayer类的对象上,即可实现动画的播放。
keyPath的初始值,默认情况下为空。当不设置fromValue的值时,动画播放的初始值取自layer对象的keyPath指定属性的当前值
@property(nullable, strong) id fromValue;
keyPath的目标值,即变动后的值
@property(nullable, strong) id toValue;
乘数。当fromValue不为空时,目标值为fromValue 乘以 byValue;当fromValue为空时,目标值为layer对象的keyPath指定属性的当前值乘以byValue
@property(nullable, strong) id byValue;
举例
平移,动画完成后会自动回到原位置。
-(void)base{
//初始化CALayer对象,并添加到控制器view的layer上
CALayer *subLayer = [CALayer layer];
subLayer.frame = CGRectMake(140, 100, 100, 100);
subLayer.backgroundColor = [UIColor yellowColor].CGColor;
subLayer.borderColor = [UIColor redColor].CGColor;
subLayer.borderWidth = 4.0;
subLayer.cornerRadius = 2.0;
[self.view.layer addSublayer:subLayer];
//延时1秒后
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//1-实例化CABasicAnimation对象
CABasicAnimation *animation = [CABasicAnimation animation];
//2-设置动画属性
animation.keyPath = @"transform.translation.y";
//锚点
animation.toValue =@100;//平移的距离是100
animation.duration = 2.0;
animation.repeatCount=3;
//3-添加动画对象到一个CALayer类的对象上,播放动画
[subLayer addAnimation:animation forKey:nil];
});
}
CASpringAnimation 弹簧动画
CASpringAnimation类是iOS9中新增的类,属于CABasicAnimation的子类,通过CASpringAnimation类可以创建具有弹簧效果的动画。
在CASpringAnimation类的定义中,包含了如下几个属性,我们可以通过设置这些属性来设置弹簧动画的展示效果。
mass:质量,影响图层运动时的惯性,mass取值越大,动画的时间越长
@property CGFloat mass;
stiffness:弹簧钢度系数,取值0~100,默认取值100
@property CGFloat stiffness;
damping:阻尼系数,影响反弹的次数,取值大于0,默认取值10
@property CGFloat damping;
初始速度,默认为0
@property CGFloat initialVelocity;
获取反弹时的停顿时间,只读属性
@property(readonly) CFTimeInterval settlingDuration;
//1-实例化对象
CASpringAnimation *animation=[CASpringAnimation animation];
//2-设置动画属性
animation.keyPath = @"transform.translation.y";
animation.fromValue=@0;
animation.toValue=@200;
animation.mass=100;
animation.stiffness=50;
animation.damping=5;
animation.initialVelocity=0;
animation.duration = 2.0;
// animation.repeatCount=3;
//3-添加动画对象到一个CALayer类的对象上,播放动画
[subLayer addAnimation:animation forKey:nil];
CAKeyFrameAnimation
关键帧动画,可以在一个values数组中设置针对某个keyPath的多个变化值,从而设计出一个相对复杂的动画播放效果,例如,我们可以设置一个CALayer对象在多个点之间来回移动,或者可以设置多个平移的值。
CAKeyframeAnimation类与CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个values数组保存多个数值,从而可以实现keyPath指定属性的复杂变化。在values中保存的每个元素都称为一个keyframe,CABasicAnimation可看做是只有2个关键帧的CAKeyframeAnimation。
@property(nullable, copy) NSArray *values;
注意:保存在values数组中的对象为NSValue类型的对象
另外,我们还可以设计layer的动画运行轨迹path,这里需要用到贝塞尔路径(UIBezierPath),还需要注意的是我们需要把UIBezierPath对象转成CGPathRef类型的对象。
@property(nullable) CGPathRef path;
举例
沿y轴,向下移动0,移动100,回到0,向上移动50
value的值表示改变多少;
-(void)keyFrame{
//初始化CALayer对象,并添加到控制器view的layer上
CALayer *subLayer = [CALayer layer];
subLayer.frame = CGRectMake(140, 100, 100, 100);
subLayer.backgroundColor = [UIColor yellowColor].CGColor;
subLayer.borderColor = [UIColor redColor].CGColor;
subLayer.borderWidth = 4.0;
subLayer.cornerRadius = 2.0;
[self.view.layer addSublayer:subLayer];
//延时1秒后
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//1-实例化对象
CAKeyframeAnimation *animation=[CAKeyframeAnimation animation];
//2-设置动画属性
animation.keyPath = @"transform.translation.y";
animation.values=@[@0,@100,@0,@-50];
animation.duration = 2.0;
// animation.repeatCount=3;
//3-添加动画对象到一个CALayer类的对象上,播放动画
[subLayer addAnimation:animation forKey:nil];
});
}
CAAnimationGroup动画组
CAAnimationGroup动画组,顾名思义就是可以创建一组动画对象,在动画播放时,图层可以同时播放多种动画的叠加效果,例如,我们可以在图层平移过程中同时修改图层的透明度。通过CAAnimationGroup类的对象,我们可以实现复杂动画的播放效果。
-(void)group{
//初始化CALayer对象,并添加到控制器view的layer上
CALayer *subLayer = [CALayer layer];
subLayer.frame = CGRectMake(140, 100, 100, 100);
subLayer.backgroundColor = [UIColor yellowColor].CGColor;
subLayer.borderColor = [UIColor redColor].CGColor;
subLayer.borderWidth = 4.0;
subLayer.cornerRadius = 2.0;
[self.view.layer addSublayer:subLayer];
//延时1秒后
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//1-实例化对象
CABasicAnimation *animation1=[CABasicAnimation animation];
//2-设置动画属性
animation1.keyPath = @"transform.translation.y";
animation1.fromValue=@0;
animation1.toValue=@200;
CABasicAnimation *animation2=[CABasicAnimation animation];
animation2.keyPath=@"opacity";
animation2.fromValue=@1;
animation2.toValue=@0.1;
CAAnimationGroup *group=[CAAnimationGroup animation];
group.animations=@[animation1,animation2];
group.duration=2.0;
//添加动画组到layer上
[subLayer addAnimation:group forKey:nil];
});
}
CATransition转场动画
CATransition转场动画可以定义图层的显示内容在切换的时候的动画效果,例如,在导航控制器使用过程中,子控制器的显示与退出效果就是通过CATransition转场动画实现的。另外,在苹果KeyNote中,当我们切换幻灯片时,也会体现切换的效果。
通过设置CATransition类中的属性,我们可以定制转场动画的效果,常用的属性主要包括:
type:动画的类型。常用的有4种:fade(渐变)、moveIn(移入)、push(推入)、reveal(移出),默认为fade(渐变)
@property(copy) NSString *type;
subType:动画的子类型,可以指定动画播放时开始的方位或方向,有4中方式:fromLeft(从左开始)、fromRight(从右开始)、fromTop(从上开始) 、fromBottom(从下开始)
@property(nullable, copy) NSString *subtype;
转场动画启动时以及结束时的进度百分比,取值为0~1,通过设置这两个属性,我们可以实现动画从中间某个状态开始播放,或者在中间某个状态提前结束。
@property float startProgress;
@property float endProgress;
例子
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic,strong)UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.imageView];
}
- (UIImageView *)imageView{
if (_imageView==nil) {
_imageView=[[UIImageView alloc]initWithFrame:CGRectMake(140, 100, 100, 100)];
UIImage *image=[UIImage imageNamed:@"1"];
[_imageView setImage:image];
}
return _imageView;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
self.imageView.image=[UIImage imageNamed:@"2"];
CATransition *animation=[CATransition animation];
// animation.type=kCATransitionFade;
//如果输入的type的值没有定义,就会使用默认的fade,渐变
animation.type=@"push";
animation.subtype=kCATransitionFromRight;
animation.duration=5;
[self.imageView.layer addAnimation:animation forKey:nil];
}
代码
https://github.com/ShaeZhuJiu/CoreAnimation_Base.git