Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍。也就是说,使用少量的代码就可以实现非常强大的功能。
Core Animation可以用在Mac OS X和iOS平台。
Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。
要注意的是,Core Animation是直接作用在CALayer上的,并非UIView。
乔帮主在2007年的WWDC大会上亲自为你演示Core Animation的强大:点击查看视频
Core Animation类的继承关系图
首先介绍两个重要的属性详情点击查看
CALayer的两个比较重要的属性
position
和anchorPoint
。
position和anchorPoint属性都是CGPoint类型的
position可以用来设置CALayer在父层中的位置,它是以父层的左上角为坐标原点(0, 0)
anchorPoint称为"定位点",它决定着CALayer身上的哪个点会在position属性所指的位置。它的x、y取值范围都是0~1,默认值为(0.5, 0.5)
一:CABasicAnimation-基本动画
基本Api介绍:
CAAnimation——所有动画对象的父类
keyPath
要改变的属性名称(传字符串)
FromValue
设置动画的初始值
ToValue
设置动画的到达值
Autoreverses
设定这个属性为 YES 时,在它到达目的地之后,动画的返回到开始的值,代替了直接跳转到开始的值,过渡平滑
Duration
设定开始值到结束值花费的时间。期间会被速度的属性所影响
RepeatCount
默认的是 0,动画只会播放一次。如果指定一个无限大的重复次数,使用 MAXFLOAT 。这个不应该和 repeatDration 属性一块使用
RepeatDuration
这个属性指定了动画应该被重复多久。动画会一直重复,直到设定的时间用完。同上它不应该和 repeatCount 一起使用
RemovedOnCompletion
这个属性默认为 YES,在指定的时间段完成后,动画就自动的从层上移除了
Speed
默认的值为 1.0.如果你改变这个值为 2.0,动画会用 2 倍的速度播放。这样的影响就是使持续时间减半。如果你指定的持续时间为 6 秒,速度为 2.0,动画就会播放 3 秒钟即一半的持续时间。
BeginTime
可以用来设置动画延迟执行时间,若想延迟1s,就设置为CACurrentMediaTime()+1,CACurrentMediaTime()为图层的当前时间
CAAnimation——动画填充模式
FillMode
这个属性一般和 RemovedOnCompletion 配合使用,保持动画状态。其中kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态.此时将RemovedOnCompletion设为NO
CAAnimation——速度控制函数
TimingFunction
控制动画运行的节奏.
kCAMediaTimingFunctionLinear(线性):匀速,给你一个相对静态的感觉 k
CAMediaTimingFunctionEaseIn(渐进):动画缓慢进入,然后加速离开
kCAMediaTimingFunctionEaseOut(渐出):动画全速进入,然后减速的到达目的地
kCAMediaTimingFunctionEaseInEaseOut(渐进渐出):动画缓慢的进入,中间加速,然后减速的到达目的地。这个是默认的动画行为。
CAAnimation——动画代理方法
CAAnimation在分类中定义了代理方法,是给NSObject添加的分类,所以任何对象,成为CAAnimation的代理都可以
@interface NSObject (CAAnimationDelegate)
/* Called when the animation begins its active duration. */
动画开始的时候调用
- (void)animationDidStart:(CAAnimation *)anim;
动画停止的时候调用
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
@end
CABasicAnimation-Example
- (void)view1Animation {
// 呼吸动画
CABasicAnimation *animation =[CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue = [NSNumber numberWithFloat:1.0f];
animation.toValue = [NSNumber numberWithFloat:0.0f];
animation.autoreverses = YES; //回退动画(动画可逆,即循环)
animation.duration = 1.0f;
animation.repeatCount = MAXFLOAT;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;//removedOnCompletion,fillMode配合使用保持动画完成效果
animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[self.view1.layer addAnimation:animation forKey:@"aAlpha"];
}
- (void)view2Animation {
// 设置旋转原点
self.view2.layer.anchorPoint = CGPointMake(0.5, 0);
CABasicAnimation* rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
//角度转弧度(这里用1,-1简单处理一下)
rotationAnimation.toValue = [NSNumber numberWithFloat:1];
rotationAnimation.fromValue = [NSNumber numberWithFloat:-1];
rotationAnimation.duration = 1.0f;
rotationAnimation.repeatCount = MAXFLOAT;
rotationAnimation.removedOnCompletion = NO;
rotationAnimation.autoreverses = YES;
rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
rotationAnimation.fillMode = kCAFillModeForwards;
[self.view2.layer addAnimation:rotationAnimation forKey:@"revItUpAnimation"];
}
- (void)view3Animation {
CABasicAnimation *moveAnimation = [CABasicAnimation animationWithKeyPath:@"position.y"];
moveAnimation.duration = 0.8;//动画时间
//动画起始值和终止值的设置
moveAnimation.fromValue = @(180);
moveAnimation.toValue = @(130);
//一个时间函数,表示它以怎么样的时间运行
moveAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
moveAnimation.repeatCount = MAXFLOAT;
moveAnimation.repeatDuration = 100;
moveAnimation.removedOnCompletion = NO;
moveAnimation.fillMode = kCAFillModeForwards;
//添加动画,后面有可以拿到这个动画的标识
[self.view3.layer addAnimation:moveAnimation forKey:@"view3Animation"];
}
二:CAKeyframeAnimation-关键帧动画
CABasicAnimation:只能从一个数值(fromValue)变到另一个数值(toValue)
CAKeyframeAnimation:会使用一个NSArray保存这些数值
CAKeyframeAnimation-Example
- (void)view4Animation {
//values方式实现
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position";
NSValue *value1 = [NSValue valueWithCGPoint:CGPointMake(50, 100)];
NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(kWindowWidth - 50, 100)];
NSValue *value3 = [NSValue valueWithCGPoint:CGPointMake(kWindowWidth - 50, kWindowHeight-50)];
NSValue *value4 = [NSValue valueWithCGPoint:CGPointMake(50, kWindowHeight-50)];
NSValue *value5 = [NSValue valueWithCGPoint:CGPointMake(50, 100)];
animation.values = @[value1,value2,value3,value4,value5];
animation.repeatCount = MAXFLOAT;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.duration = 6.0f;
animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.view4.layer addAnimation:animation forKey:@"values"];
}
- (void)view5Animation {
// path方式实现
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position";
CGMutablePathRef path = CGPathCreateMutable();
//矩形线路
CGPathAddRect(path, NULL, CGRectMake(50,100, kWindowWidth - 50,kWindowHeight - 50));
animation.path=path;
CGPathRelease(path);
animation.repeatCount = MAXFLOAT;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.duration = 6.0f;
animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.view4.layer addAnimation:animation forKey:@"path"];
}
- (void)view6Animation {
//keyTimes演示
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
//animation.keyPath = @"transform.translation.x";
animation.keyPath = @"position.x";
animation.values = @[@0, @20, @-20, @20, @0];
animation.keyTimes = @[ @0, @(1 / 6.0), @(3 / 6.0), @(5 / 6.0), @1 ];
animation.duration = 6;
animation.additive = YES;
[self.view4.layer addAnimation:animation forKey:@"keyTimes"];
}
- (void)view7Animation {
// 跟随路径移动动画
//创建路径
UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
[bezierPath moveToPoint:CGPointMake(0, 450)];
[bezierPath addCurveToPoint:CGPointMake(370, 500) controlPoint1:CGPointMake(350, 200) controlPoint2:CGPointMake(300, 600)]; //一个曲线
//路径样式
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = bezierPath.CGPath;
shapeLayer.fillColor = [UIColor clearColor].CGColor; //填充色<默认黑色>
shapeLayer.strokeColor = [UIColor blueColor].CGColor; //线色
shapeLayer.lineWidth = 2;
[self.view.layer addSublayer:shapeLayer];
CAKeyframeAnimation *animaiton = [CAKeyframeAnimation animationWithKeyPath:@"position"];
NSArray *rotationVelues = @[@(M_PI_4), @(-M_PI_4), @(M_PI_4)];
animaiton.values = rotationVelues;
animaiton.rotationMode = kCAAnimationRotateAuto; //方向
animaiton.duration = 3.0f;
animaiton.keyTimes = @[@0.2 ,@0.8 ,@1];
animaiton.path = bezierPath.CGPath;
animaiton.repeatCount = HUGE_VALF; // #define HUGE_VALF 1e50f
[self.view4.layer addAnimation:animaiton forKey:@"path"];
}
- (void)popJumpAnimationView:(UIView *)sender {
// 上下跳动动画
CGFloat duration = 0.4f;
CGFloat height = 25.f;
CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.y"];
CGFloat currentTy = sender.transform.ty;
animation.duration = duration;
animation.values = @[@(currentTy), @(currentTy - height/4), @(currentTy-height/4*2), @(currentTy-height/4*3), @(currentTy - height), @(currentTy-height/4*3), @(currentTy -height/4*2), @(currentTy - height/4), @(currentTy)];
animation.keyTimes = @[ @(0), @(0.025), @(0.085), @(0.2), @(0.5), @(0.8), @(0.915), @(0.975), @(1) ];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.repeatCount = 1;
[sender.layer addAnimation:animation forKey:@"kViewShakerAnimationKey"];
}
三:CAAnimationGroup-动画组
CAAnimationGroup-Example
- (void)view8Animation {
CABasicAnimation * animationScale = [CABasicAnimation animation];
animationScale.keyPath = @"transform.scale";
animationScale.toValue = @(0.1);
CABasicAnimation *animationRota = [CABasicAnimation animation];
animationRota.keyPath = @"transform.rotation";
animationRota.toValue = @(M_PI_2);
CAAnimationGroup * group = [[CAAnimationGroup alloc] init];
group.duration = 3.0;
group.fillMode = kCAFillModeForwards;
group.removedOnCompletion = NO;
group.repeatCount = MAXFLOAT;
group.animations = @[animationScale,animationRota];
[self.view5.layer addAnimation:group forKey:nil];
}
四:CATransition-转场动画
CATransitionApi介绍:
CATransition是CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。iOS比Mac OS X的转场动画效果少一点
UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果
动画属性:(有的属性是具备方向的,详情看下图)
/* The name of the transition. Current legal transition types include
* `fade', `moveIn', `push' and `reveal'. Defaults to `fade'. */
type
动画过渡类型
常见类型
pageCurl 向上翻一页
pageUnCurl 向下翻一页
rippleEffect 滴水效果
suckEffect 收缩效果,如一块布被抽走
cube 立方体效果
oglFlip 上下翻转效果
/* An optional subtype for the transition. E.g. used to specify the
* transition direction for motion-based transitions, in which case
* the legal values are `fromLeft', `fromRight', `fromTop' and
* `fromBottom'. */
subtype
动画过渡方向
startProgress
动画起点(在整体动画的百分比)
endProgress
动画终点(在整体动画的百分比)
CATransition-Example
- (void)view10Animation {
self.imageView.userInteractionEnabled = YES;
//添加手势
UISwipeGestureRecognizer *leftSwipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe:)];
leftSwipe.direction = UISwipeGestureRecognizerDirectionLeft;
[self.imageView addGestureRecognizer:leftSwipe];
UISwipeGestureRecognizer *rightSwipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe:)];
rightSwipe.direction = UISwipeGestureRecognizerDirectionRight;
[self.imageView addGestureRecognizer:rightSwipe];
}
static int _imageIndex = 0;
- (void)swipe:(UISwipeGestureRecognizer *)swipe {
//转场代码与转场动画必须得在同一个方法当中.
NSString *dir = nil;
if (swipe.direction == UISwipeGestureRecognizerDirectionLeft) {
_imageIndex++;
if (_imageIndex > 4) {
_imageIndex = 0;
}
NSString *imageName = [NSString stringWithFormat:@"%d.jpg",_imageIndex];
self.imageView.image = [UIImage imageNamed:imageName];
dir = @"fromRight";
}else if (swipe.direction == UISwipeGestureRecognizerDirectionRight) {
_imageIndex--;
if (_imageIndex < 0) {
_imageIndex = 4;
}
NSString *imageName = [NSString stringWithFormat:@"%d.jpg",_imageIndex];
self.imageView.image = [UIImage imageNamed:imageName];
dir = @"fromLeft";
}
//添加动画
CATransition *anim = [CATransition animation];
//设置转场类型
anim.type = @"cube";
//设置转场的方向
anim.subtype = dir;
anim.duration = 0.5;
//动画从哪个点开始
//anim.startProgress = 0.2;
//anim.endProgress = 0.3;
[self.imageView.layer addAnimation:anim forKey:nil];
}