iOS中的动画无非是两种形式,一种是UIView动画,一种是Core Animation动画,即核心动画,也叫layer层动画.上一篇讲过了UIView动画,那我们趁热打铁,这一篇讲一讲核心动画.核心动画是利用的Core Animation框架。Core Animation是iOS和macOS平台上负责图形渲染与动画的基础框架。Core Animation可以作用与动画视图或者其他可视元素,为你完成了动画所需的大部分绘帧工作。你只需要配置少量的动画参数(如开始点的位置和结束点的位置)即可使用Core Animation的动画效果。Core Animation将大部分实际的绘图任务交给了图形硬件来处理,图形硬件会加速图形渲染的速度。这种自动化的图形加速技术让动画拥有更高的帧率并且显示效果更加平滑,不会加重CPU的负担而影响程序的运行速度。
Core Animation又叫layer层动画,那我们先说下什么是CALayer,CALayer包含在QuartzCore框架中,这是一个跨平台的框架,在使用Core Animation开发动画的本质就是将CALayer中的内容转化为位图从而供硬件操作,所以要熟练掌握核心动画操作必须先来熟悉CALayer.其实layer和view基本是类似的,也有frame,也有backgroundColor,唯一的不同点是view能相应事件,而layer则不能.那么layer有哪些属性呢?
上一张图说明一下属性
//举个例子说明下使用方法
CALayer *layer = [[CALayer alloc]init];
layer.frame=CGRectMake(0, 0, 100, 100);
//设置图片
UIImage *image =[UIImage imageNamed:@"1.png"];
layer.contents=(__bridge id _Nullable)(image.CGImage);
layer.cornerRadius = 10;
//以下五项需要一起设置才能出来效果
//设置背景
layer.backgroundColor=[UIColor blueColor].CGColor;
//阴影模糊度
layer.shadowRadius = 10;
//设置阴影颜色
layer.shadowColor =[UIColor greenColor].CGColor;
//设置偏移量
layer.shadowOffset = CGSizeMake(40, 40);
//设置透明度
layer.shadowOpacity=1;
//设置边框宽度
layer.borderWidth = 3;
//设置边框颜色
layer.borderColor = [UIColor yellowColor].CGColor;
//position用来设置layer层在父层的位置以父层的左上角为0
//anchor point 默认是(0.5,0.5),按比例移动自己
//设置锚点
layer.anchorPoint = CGPointMake(0.5, 0.5);
[self.view.layer addSublayer:layer];
那么接下来我们入正题,首先我们看一下Core Animation类的继承关系图
从图中我们可以看出,有五个类都继承自CAAnimation.那么我们将要使用到的就是这五个子类.他们分别是:基础动画(CABasicAnimation)、关键帧动画(CAKeyFrameAnimation)、动画组(CAAnimationGroup)、转场动画(CATransition).接下来对他们分别进行介绍一下:
- CAAnimation:核心动画的基础类,也是其他动画类的父类,不能直接使用,负责动画持续时间、速度控制和重复次数,本身是实现了CAMediaTiming协议
- CAPropertyAnimation:属性动画的基类,即通过属性进行动画设置,不能直接使用。
- CAAnimationGroup:动画组,可以通过动画组来进行所有动画行为的统一控制,组中所有动画可以并发执行。
- CATransition:提供了转场动画时图层变化的过渡效果,主要通过滤镜进行动画效果设置。
- CABasicAnimation:基础动画,通过修改属性进行动画参数控制,比如:位移、透明度、缩放、旋转、背景色等等,只有初始状态和结束状态。
- CAKeyFrameAnimation:关键帧动画,通过修改属性进行动画,可以有多个状态控制。
接下来说一下常用属性
duration : 动画的持续时间
beginTime : 动画的开始时间
repeatCount : 动画的重复次数
autoreverses : 执行的动画按照原动画返回执行
timingFunction : 控制动画的显示节奏系统提供五种值选择,分别是:
kCAMediaTimingFunctionLinear 线性动画
kCAMediaTimingFunctionEaseIn 先快后慢
kCAMediaTimingFunctionEaseOut 先慢后快
kCAMediaTimingFunctionEaseInEaseOut 先慢后快再慢
kCAMediaTimingFunctionDefault 默认,也属于中间比较快
delegate : 动画代理。能够检测动画的执行和结束。
@interface NSObject (CAAnimationDelegate)
- (void)animationDidStart:(CAAnimation *)anim;
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
@end
path:关键帧动画中的执行路径
type:过渡动画的动画类型,系统提供了四种过渡动画。
kCATransitionFade 渐变效果
kCATransitionMoveIn 进入覆盖效果
kCATransitionPush 推出效果
kCATransitionReveal 揭露离开效果
subtype : 过渡动画的动画方向
kCATransitionFromRight 从右侧进入
kCATransitionFromLeft 从左侧进入
kCATransitionFromTop 从顶部进入
kCATransitionFromBottom 从底部进入
重点来了~~~
实现简单动画通常都用CABasicAnimation对象和用户配置好的动画参数来实现,通过调用basicAni的addAnimation:forKey:方法将动画添加到layer里面,这个方法会根据填入的key值来决定让哪个属性进行动画。
图层动画的本质就是将图层内部的内容转化为位图经硬件操作形成一种动画效果,其实图层本身并没有任何的变化,也就是说动画不会从根本上改变layer的属性,只是展示属性变化的效果
#pragma mark === 永久闪烁的动画 ======
-(CABasicAnimation *)opacityForeverAnimation:(float)time{
//必须写opacity才行。这是透明度。
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
//fromValue可以不写,默认是当前状态
animation.fromValue = [NSNumber numberWithFloat:1.0f];
animation.toValue = [NSNumber numberWithFloat:0.0f];
animation.autoreverses = YES;
animation.duration = 1.0f;
animation.repeatCount = MAXFLOAT;
//要做无限循环的动画,动画的removedOnCompletion属性必须设置为NO,否则运行一次动画就会销毁
animation.removedOnCompletion = NO;
//保持动画最终状态
animation.fillMode = kCAFillModeForwards;
//没有的话是均匀的动画。
animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
return animation;
}
//然后再viewDidLoad调用方法就可以了
[self.myTest1.layer addAnimation:[self opacityForeverAnimation:0.5] forKey:nil];
//当然animationWithKeyPath:后面还可以跟@"backgroundColor"修改背景颜色,@"transform.translation.x"或者@"transform.translation.y"这样就是横向、纵向移动了,也可以是@"transform.scale",这样就变成了缩放效果,还可以是@"position",这样就变成了路径动画等等
关键帧动画(CAKeyframeAnimation)
CAKeyframeAnimation和CABaseAnimation都属于CAPropertyAnimatin的子类。CABaseAnimation只能从一个数值(fromValue)变换成另一个数值(toValue),而CAKeyframeAnimation则会使用一个NSArray保存一组关键帧。
- values:就是上述的NSArray对象。里面的元素称为”关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧
- path:可以设置一个CGPathRef\CGMutablePathRef,让层跟着路径移动。path只对CALayer的anchorPoint和position起作用。如果你设置了path,那么values将被忽略。
- keyTimes:可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧.当keyTimes没有设置的时候,各个关键帧的时间是平分的。
//path动画
CAKeyframeAnimation *anima = [CAKeyframeAnimation animationWithKeyPath:@"position"];
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(SCREEN_WIDTH/2-100, SCREEN_HEIGHT/2-100, 200, 200)];
anima.path = path.CGPath;
anima.duration = 2.0f;
[_demoView.layer addAnimation:anima forKey:@"pathAnimation"];
//抖动效果
-(void)shakeAnimation{
CAKeyframeAnimation *anima = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
//在这里@"transform.rotation"==@"transform.rotation.z"
NSValue *value1 = [NSNumber numberWithFloat:-M_PI/180*4];
NSValue *value2 = [NSNumber numberWithFloat:M_PI/180*4];
NSValue *value3 = [NSNumber numberWithFloat:-M_PI/180*4];
anima.values = @[value1,value2,value3];
anima.repeatCount = MAXFLOAT;
[_demoView.layer addAnimation:anima forKey:@"shakeAnimation"];
}
组动画(CAAnimationGroup)
CAAnimation的子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行。
- animations: 用来保存一组动画对象的NSArray
CAKeyframeAnimation *anima1 = [CAKeyframeAnimation animationWithKeyPath:@"position"];
NSValue *value0 = [NSValue valueWithCGPoint:CGPointMake(0, SCREEN_HEIGHT/2-50)];
NSValue *value1 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH/3, SCREEN_HEIGHT/2-50)];
NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH/3, SCREEN_HEIGHT/2+50)];
NSValue *value3 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH*2/3, SCREEN_HEIGHT/2+50)];
NSValue *value4 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH*2/3, SCREEN_HEIGHT/2-50)];
NSValue *value5 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-50)];
anima1.values = [NSArray arrayWithObjects:value0,value1,value2,value3,value4,value5, nil];
//缩放动画
CABasicAnimation *anima2 = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
anima2.fromValue = [NSNumber numberWithFloat:0.8f];
anima2.toValue = [NSNumber numberWithFloat:2.0f];
//旋转动画
CABasicAnimation *anima3 = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
anima3.toValue = [NSNumber numberWithFloat:M_PI*4];
//组动画
CAAnimationGroup *groupAnimation = [CAAnimationGroup animation];
groupAnimation.animations = [NSArray arrayWithObjects:anima1,anima2,anima3, nil];
groupAnimation.duration = 4.0f;
[_demoView.layer addAnimation:groupAnimation forKey:@"groupAnimation"];
过渡动画也叫转场动画(CATransition)
CAAnimation的子类,用于做过渡动画或者转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。
type:动画过渡类型
Apple 官方的SDK其实只提供了四种过渡效果。
- kCATransitionFade 渐变淡出效果
- kCATransitionMoveIn 进入覆盖效果
- kCATransitionPush 推出效果
- kCATransitionReveal 揭露离开效果
私有API提供了其他很多非常炫的过渡动画,比如 - @"cube" 方块
- @"suckEffect" 三角收缩效果,如一块布被抽走
- @"oglFlip" 上下翻转
- @"rippleEffect" 水波抖动
- @"pageCurl" 上翻页
- @"pageUnCurl" 下翻页
- @"cameraIrisHollowOpen" 镜头快门开
- @"cameraIrisHollowClose" 镜头快门关
注意:上面的私有api可以安全使用,但是下面列举的几种API不建议开发者们使用。因为苹果公司不提供维护,并且有可能造成你的app审核不通过。
- @"spewEffect" 新版面在屏幕下方中间位置被释放出来覆盖旧版面
- @"genieEffect" 旧版面在屏幕左下方或右下方被吸走, 显示出下面的新版面
- @"unGenieEffect" 新版面在屏幕左下方或右下方被释放出来覆盖旧版面
- @"twist" 版面以水平方向像龙卷风式转出来
- @"tubey" 版面垂直附有弹性的转出来
- @"swirl" 旧版面360度旋转并淡出, 显示出新版面
- @"charminUltra" 旧版面淡出并显示新版面
- @"zoomyIn" 新版面由小放大走到前面, 旧版面放大由前面消失
- @"zoomyOut" 新版面屏幕外面缩放出现, 旧版面缩小消失
- @"oglApplicationSuspend" 像按”home” 按钮的效果
subtype:动画过渡方向
- kCATransitionFromRight 从右侧进入
- kCATransitionFromLeft 从左侧进入
- kCATransitionFromTop 从顶部进入
- kCATransitionFromBottom 从底部进入
- startProgress:动画起点(在整体动画的百分比)
- endProgress:动画终点(在整体动画的百分比)
看一下怎么使用
@property (nonatomic , assign) NSInteger index;
_index = 0;
//设置view的值
-(void)changeView : (BOOL)isUp{
if (_index>3) {
_index = 0;
}
if (_index<0) {
_index = 3;
}
NSArray *colors = [NSArray arrayWithObjects:[UIColor cyanColor],[UIColor magentaColor],[UIColor orangeColor],[UIColor purpleColor], nil];
NSArray *titles = [NSArray arrayWithObjects:@"1",@"2",@"3",@"4", nil];
_demoView.backgroundColor = [colors objectAtIndex:_index];
_demoLabel.text = [titles objectAtIndex:_index];
if (isUp) {
_index++;
}else{
_index--;
}
}
//逐渐消失
-(void)fadeAnimation{
[self changeView:YES];
CATransition *anima = [CATransition animation];
anima.type = kCATransitionFade;//设置动画的类型
anima.subtype = kCATransitionFromRight; //设置动画的方向
//anima.startProgress = 0.3;//设置动画起点
//anima.endProgress = 0.8;//设置动画终点
anima.duration = 1.0f;
[_demoView.layer addAnimation:anima forKey:@"fadeAnimation"];
}