一、Core Animation简介
(1)Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果
(2)Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。
(3)Core Animation是直接作用在CALayer上的,并非UIView。
二、Core Animation的使用步骤
1.使用它需要先添加QuartzCore.framework框架和引人主头文件
2.初始化一个CAAnimation对象,并设置一些动画相关属性
3.通过调用CALayer的addAnimation:forKey:方法增加CAAnimation对象到CALayer中,这样就能开始执行动画了
4.通过调用CALayer的removeAnimationForKey:方法可以停止CALayer中的动画
1.过渡动画(转场动画)
CATransition
(1)视图切换
(2)控制器切换
实例:
//创建一个转场动画
CATransition *transition = [CATransition animation];
//设置动画时间
transition.duration = 1;
//动画类型
/*
CATransition中type的值:
1 fade = 1, //淡入淡出
2 push, //推挤
3 reveal, //揭开
4 moveIn, //覆盖
5 cube, //立方体
6 suckEffect, //吮吸
7 oglFlip, //翻转
8 rippleEffect, //波纹
9 pageCurl, //翻页
10 pageUnCurl, //反翻页
11 cameraIrisHollowOpen, //开镜头
12 cameraIrisHollowClose, //关镜头
*/
transition.type = @"pageCurl";
//动画方向
transition.subtype = kCATransitionFromLeft;
//执行动画
[self.imageView.layer addAnimation:transition forKey:nil];
2.关键帧动画
CAKeyframeAnimation
实例
//关键帧动画
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
//动画时间
animation.duration = 5;
//设置关键点
animation.values = @[
[NSValue valueWithCGPoint:CGPointMake(130, 130)],
[NSValue valueWithCGPoint:CGPointMake(300, 500)],
[NSValue valueWithCGPoint:CGPointMake(300, 40)],
[NSValue valueWithCGPoint:CGPointMake(30, 40)]
];
//设置运行的速率
/*
* kCAMediaTimingFunctionLinear 线性,即匀速
* kCAMediaTimingFunctionEaseIn 先慢后快
* kCAMediaTimingFunctionEaseOut 先快后慢
* kCAMediaTimingFunctionEaseInEaseOut 先慢后快再慢
* kCAMediaTimingFunctionDefault 实际效果是动画中间比较快.
*/
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
//原路返回
//animation.autoreverses = YES;
//动画次数
animation.repeatCount = 1;
//停留在终点
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
//执行动画
[redLayer addAnimation:animation forKey:nil];
构造路径、矩形、圆弧/圆心、线段、带有圆角的矩形、椭圆
//路径
CGMutablePathRef path = CGPathCreateMutable();
#if 0
//矩形
CGPathAddRect(path, NULL, CGRectMake(30, 50, 300, 300));
//圆弧,圆心(200,200) 半径100 开始弧度0 结束M_PI, true表示逆时针
CGPathAddArc(path, NULL, 200, 200, 100, 0, M_PI, false);
//线段
CGPoint point[3] = {CGPointMake(30, 30),CGPointMake(300, 300),CGPointMake(300, 30),};
CGPathAddLines(path, NULL, point, sizeof(point)/sizeof(point[0]));
//带有圆角的矩形
CGPathAddRoundedRect(path, NULL, CGRectMake(30, 50, 300, 300), 100, 100);
#endif
//椭圆
CGPathAddEllipseInRect(path, NULL, CGRectMake(30, 40, 300, 500));
//构造贝塞尔曲线
// CGPathAddCurveToPoint(<#CGMutablePathRef _Nullable path#>, <#const CGAffineTransform * _Nullable m#>, <#CGFloat cp1x#>, <#CGFloat cp1y#>, <#CGFloat cp2x#>, <#CGFloat cp2y#>, <#CGFloat x#>, <#CGFloat y#>)
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
//动画时间
animation.duration = 3;
//设置动画路径
animation.path = path;
//设置动画重复次数
animation.repeatCount = MAXFLOAT;
//执行动画
[redLayer addAnimation:animation forKey:nil];
//移除动画
//[redLayer removeAnimationForKey:<#(nonnull NSString *)#>];
CGPathRelease(path);
(1)values
(2)path(加入购物车)
(3)输入框输入错误动画
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position.x"];
animation.duration = 0.15;
//关键点
animation.values = @[@(10),@(0),@(-10),@(0)];
//相对于当前的坐标为参考,也就是在当前的位置基础上移动了多少
animation.additive = YES;
//动画次数
animation.repeatCount = 2;
[self.textField.layer addAnimation:animation forKey:nil];
}
(4)视图抖动效果(系统桌面图标删除效果)
//角度转化为弧度
#define kToDian(angle) (M_PI/180 * (angle))
//长按
- (void)handleLongPress:(UILongPressGestureRecognizer *)longPress
{
if (longPress.state == UIGestureRecognizerStateBegan)
{
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
animation.values = @[@(kToDian(5)),@(kToDian(0)),@(kToDian(-5)),@(kToDian(0))];
animation.duration = 0.2;
animation.repeatCount = MAXFLOAT;
//执行动画
[longPress.view.layer addAnimation:animation forKey:@"animaiton"];
//3秒停止动画
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//停止动画 - 移除指定动画
[longPress.view.layer removeAnimationForKey:@"animaiton"];
//移除所有动画
//[longPress.view.layer removeAllAnimations];
});
}
}
(5)点赞动画
calculationMode 是控制关键帧动画时间的另一种方法。我们通过将其设置为 kCAAnimationPaced,让 Core Animation 向被驱动的对象施加一个恒定速度,不管路径的各个线段有多长。
additive 属性为 YES 能够对所有形式的需要更新的元素重用相同的动画,且无需提前知道它们的位置。
3.隐式动画
CABasicAnimation
(1)旋转
//隐式动画
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
animation.duration = 1;
//结束的位置
animation.toValue = @(M_PI * 2);
//
animation.repeatCount = MAXFLOAT;
[imageView.layer addAnimation:animation forKey:nil];
(2)摇一摇(微信摇一摇)
//启动摇一摇
[UIApplication sharedApplication].applicationSupportsShakeToEdit = YES;
/**
* 摇一摇开始会触发
*
* @param motion <#motion description#>
* @param event <#event description#>
*/
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"shake_sound_male.wav" ofType:nil];
//1.播放音频
_player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:nil];
//播放音频
[_player play];
//2.动画
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
animation.duration = 0.5;
//原路返回
animation.autoreverses = YES;
//向上移动25
animation.toValue = @(-25);
[self.topImageView.layer addAnimation:animation forKey:nil];
//下面的图片向下移动 25
animation.toValue = @(25);
[self.bottomImageView.layer addAnimation:animation forKey:nil];
//TODO::请求数据
}
byValue和toValue的区别,前者是在当前的位置上增加多少,后者是到指定的位置。
4.CAAnimationGroup 动画组
变色变形效果例子
/*
1.背景颜色动画
*/
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
//动画时间
animation.duration = 3;
//动画起始状态
animation.fromValue = (__bridge id _Nullable)([UIColor redColor].CGColor);
//动画终点状态
animation.toValue = (__bridge id _Nullable)([UIColor greenColor].CGColor);
animation.autoreverses = YES;
animation.repeatCount = MAXFLOAT;
//执行动画
[layer addAnimation:animation forKey:nil];
/*
2.圆角半径动画
*/
CABasicAnimation *cornerRadiusAnimation = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
//动画时间
cornerRadiusAnimation.duration = 3;
//动画起始状态
cornerRadiusAnimation.fromValue = @(0);
//动画终点状态
cornerRadiusAnimation.toValue = @(100);
cornerRadiusAnimation.autoreverses = YES;
cornerRadiusAnimation.repeatCount = MAXFLOAT;
//执行动画
[layer addAnimation:cornerRadiusAnimation forKey:nil];
仿真动画
/**
* 重力行为
*/
@property (nonatomic, strong) UIGravityBehavior *gravity;
/**
* 碰撞行为
*/
@property (nonatomic, strong) UICollisionBehavior *collision;
/**
* 仿真行为的执行者
*/
@property (nonatomic, strong) UIDynamicAnimator *animator;
/**
* 仿真行为的执行者
*/
- (UIDynamicAnimator *)animator
{
if (!_animator)
{
_animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
}
return _animator;
}
/**
* 重力行为
*
* @return <#return value description#>
*/
- (UIGravityBehavior *)gravity
{
if (!_gravity)
{
_gravity = [[UIGravityBehavior alloc] init];
}
return _gravity;
}
/**
* 碰撞行为
*/
- (UICollisionBehavior *)collision
{
if (!_collision)
{
_collision = [[UICollisionBehavior alloc] init];
//设置边沿
_collision.translatesReferenceBoundsIntoBoundary = YES;
}
return _collision;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(createItem) userInfo:nil repeats:YES];
}
/**
* 创建仿真对象,并在添加重力和碰撞行为,然后执行
*/
- (void)createItem
{
/*
仿真行为:
1、要有仿真元素。一般是UIView。
2.仿真行为。
3.仿真行为执行者。
*/
//仿真元素
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(arc4random_uniform(self.view.frame.size.width) - 40, 40, 40, 40)];
view.backgroundColor = [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1.0];
[self.view addSubview:view];
//添加重力行为
[self.gravity addItem:view];
//添加碰撞行为
[self.collision addItem:view];
//执行重力行为
[self.animator addBehavior:self.gravity];
//执行碰撞行为
[self.animator addBehavior:self.collision];
}