Core Animation是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果
开发步骤
:
①
初始化一个动画对象
(CAAnimation)
并设置一些动画相关属性
②
添加动画对象到层
(CALayer)
中,开始执行动画
CALayer
中很多属性都可以通过
CAAnimation
实现动画效果,包括:
opacity
、
position
、
transform
、
bounds
、
contents
等
(
可以在
API
文档中搜索:
CALayer Animatable Properties
)
通过调用
CALayer
的
addAnimation:forKey
增加动画到层
(CALayer)
中
,这样就能触发动画了
。通过调用
removeAnimationForKey
可以
停止层中的动画
Core Animation
的动画执行过程都是在后台操作的,不会阻塞主线程
CAAnimation
所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类
属性解析:
(
红色代表来自
CAMediaTiming
协议的属性
)
duration
:动画的持续时间
repeatCount
:动画的重复次数
repeatDuration
:动画的重复时间
removedOnCompletion
:默认为
YES
,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为
NO
,不过还要设置
fillMode
为
kCAFillModeForwards
fillMode
:决定当前对象在非
active
时间段的行为
.
比如动画开始之前
,
动画结束之后
beginTime
:可以用来设置动画延迟执行时间,若想延迟
2s
,就设置为
CACurrentMediaTime
()+2
,
CACurrentMediaTime
()
为图层的当前时间
timingFunction
:速度控制函数,控制动画运行的节奏
delegate
:动画代理
CAPropertyAnimation
是CAAnimation的子类,也是个抽象类,要想创建动画对象,应该使用它的两个子类:CABasicAnimation和CAKeyframeAnimation
属性解析:
keyPath:通过指定CALayer的一个属性名称为keyPath(NSString类型),并且对CALayer的这个属性的值进行修改,达到相应的动画效果。
CABasicAnimation
CAPropertyAnimation的子类
属性解析:
fromValue:keyPath相应属性的初始值
toValue:keyPath相应属性的结束值
随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue
如果fillMode=kCAFillModeForwards和removedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。比如,CALayer的position初始值为(0,0),CABasicAnimation的fromValue为(10,10),toValue为(100,100),虽然动画执行完毕后图层保持在(100,100)这个位置,实质上图层的position还是为(0,0)
CAKeyframeAnimation
CApropertyAnimation
的子类,跟
CABasicAnimation
的区别是:
CABasicAnimation
只能从一个数值
(
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
没有设置的时候
,
各个关键帧的时间是平分的
CABasicAnimation
可看做是最多只有
2
个关键帧的
CAKeyframeAnimation
CAAnimationGroup
CAAnimation
的子类,可以保存一组动画对象,将
CAAnimationGroup
对象加入层后,组中所有动画对象可以同时并发运行
属性解析:
animations
:用来保存一组动画对象的
NSArray
默认情况下,一组动画对象是同时运行的,也可以通过设置动画对象的
beginTime
属性来更改动画的开始时间
CATransition
CAAnimation
的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。
iOS
比
Mac OS X
的
转场
动画效果少一点
UINavigationController
就是通过
CATransition
实现了将控制器的视图推入屏幕的动画效果
属性解析
:
type
:动画过渡类型
subtype
:动画过渡方向
startProgress
:动画起点
(
在整体动画的百分比
)
endProgress
:动画终点
(
在整体动画的百分比
)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
示例:CABasicAnimation
大小的动画:
// 通过核心动画实现在根层执行动画
// 核心动画的使用步骤
// 1、创建一个动画对象
CABasicAnimation *animation = [CABasicAnimation animation];
#warning 核心动画只是一个假象,真是的大小是没有变化的
// 设置图层的 “属性” 来决定 “动画的类型”
// bounds:图层大小改变的动画
animation.keyPath = @"bounds";
// 设置bounds尺寸变化后的大小
animation.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
// 使动画保存执行之后的状态
animation.removedOnCompletion = NO;// 动画对象不要移除(YES:动画执行完后移除动画对象(默认))
animation.fillMode = kCAFillModeForwards;// 保存当前的状态
// 2、往控件的图层上添加动画(控件的图层是根图层)
[self.imageView.layer addAnimation:animation forKey:nil];
位置的动画1:
//1.创建一个动画对象
CABasicAnimation *animation = [CABasicAnimation animation];
//设置动画类型
animation.keyPath = @"position";
//动画执行的 "初始状态"
//animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
//动画执行的 "最终状态"
//animation.toValue = [NSValue valueWithCGPoint:CGPointMake(100, 250)];
//每次动画执行的 "增加值"
animation.byValue = [NSValue valueWithCGPoint:CGPointMake(10, 10)];
//保存动画执行状态
//解决方案2:使动画保存执行之后的状态,只要设置动画的两个属性
animation.removedOnCompletion = NO;//动画对象不要移除
animation.fillMode = kCAFillModeForwards;//保存当前的状态
//2.往控件的图层添加动画
[self.imageView.layer addAnimation:animation forKey:nil];
位置的动画2:
//1.创建一个动画对象
CABasicAnimation *animation = [CABasicAnimation animation];
//设置动画类型
//animation.keyPath = @"transform.translation";
animation.keyPath = @"transform.translation.x";
//每次动画执行的 "增加值"
//animation.byValue = [NSValue valueWithCGPoint:CGPointMake(10, 10)];
//byValue的数据类型 由 keyPath 决定
animation.byValue = @10;
//保存动画执行状态
//解决方案2:使动画保存执行之后的状态,只要设置动画的两个属性
animation.removedOnCompletion = NO;//动画对象不要移除
animation.fillMode = kCAFillModeForwards;//保存当前的状态
//2.往控件的图层添加动画
[self.imageView.layer addAnimation:animation forKey:nil];
旋转的动画:
//核心动画使用步骤
//1.创建一个动画对象
CABasicAnimation *animation = [CABasicAnimation animation];
//设置动画类型
animation.keyPath = @"transform.rotation.x";
//每次动画执行的 "增加值"
//byValue的数据类型 由 keyPath 决定
animation.byValue = @(M_PI_4);
//保存动画执行状态
//解决方案2:使动画保存执行之后的状态,只要设置动画的两个属性
animation.removedOnCompletion = NO;//动画对象不要移除
animation.fillMode = kCAFillModeForwards;//保存当前的状态
//2.往控件的图层添加动画
[self.imageView.layer addAnimation:animation forKey:nil];
缩放的动画:
//1.创建一个动画对象
CABasicAnimation *animation = [CABasicAnimation animation];
//设置动画类型 -》 keyPath设置图层的属性 bounds/position/transform。。。。
animation.keyPath = @"transform.scale.x";
// 设置动画的时间
animation.duration = 3;
//每次动画执行的 "增加值"
//byValue的数据类型 由 keyPath 决定
animation.byValue = @1.5;
//保存动画执行状态
//解决方案2:使动画保存执行之后的状态,只要设置动画的两个属性
animation.removedOnCompletion = NO;//动画对象不要移除
animation.fillMode = kCAFillModeForwards;//保存当前的状态
//2.往控件的图层添加动画
[self.imageView.layer addAnimation:animation forKey:nil];
帧动画:沿着指定路径执行的动画
//创建一个帧动画
CAKeyframeAnimation *animaiton = [CAKeyframeAnimation animation];
animaiton.keyPath = @"position";
//设置动画执行的路径 指定四个点
NSValue *value1 = [NSValue valueWithCGPoint:CGPointMake(50, 50)];
NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(250, 50)];
NSValue *value3 = [NSValue valueWithCGPoint:CGPointMake(250, 250)];
NSValue *value4 = [NSValue valueWithCGPoint:CGPointMake(50, 250)];
//数组第一个是 “开始状态” 最后一个是 "结束状态"
animaiton.values = @[value1,value2,value3,value4,value1];
//设置时间
animaiton.duration = 5;
//设置动画节奏
//kCAMediaTimingFunctionEaseIn 先慢后快
//kCAMediaTimingFunctionEaseOut 先快后慢
//kCAMediaTimingFunctionLinear 线性匀速
//kCAMediaTimingFunctionEaseInEaseOut 中间快两边慢
animaiton.timingFunction =[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
#warning 内部的path的优级大小values优先级
//设置路径
CGMutablePathRef path = CGPathCreateMutable();
CGFloat screenW = [UIScreen mainScreen].bounds.size.width;
CGPathAddEllipseInRect(path, NULL, CGRectMake(0, 0, screenW, screenW));
animaiton.path = path;
//c语言的数据类型 如果create/copy/retain创建要释放
CFRelease(path);
//添加动画
[self.imgView.layer addAnimation:animaiton forKey:nil];
帧动画示例(图片抖动):
@interface ViewController ()
- (IBAction)start;
- (IBAction)stop;
@property (weak, nonatomic) IBOutlet UIImageView *imgIcon;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)start {
//抖动图片 使用帧动画 设置 旋转的 路径
CAKeyframeAnimation *rotationAni = [CAKeyframeAnimation animation];
rotationAni.keyPath = @"transform.rotation";
//计算好旋转的弧度
CGFloat angle = M_PI_4;
//设置 旋转的路径
rotationAni.values = @[@(-angle),@(angle),@(-angle)];
//设置动画执行的次数
rotationAni.repeatCount = MAXFLOAT;
[self.imgIcon.layer addAnimation:rotationAni forKey:@"shake"];
}
- (IBAction)stop {
//通过key把动画移除,也就是把动画停止
[self.imgIcon.layer removeAnimationForKey:@"shake"];
}
CATransition
转场动画:图片浏览器例子
#import "ViewController.h"
#define AnimationDuration 2
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imgView;
- (IBAction)tapView:(UITapGestureRecognizer *)sender;
@property(nonatomic,strong)NSMutableArray *imgs;
@property(nonatomic,assign)NSInteger currentImgIndex;//当前图片的索引
@end
@implementation ViewController
-(NSMutableArray *)imgs{
if (!_imgs) {
_imgs = [NSMutableArray array];
for (NSInteger i = 1; i < 10; i++) {
NSString *imgName = [NSString stringWithFormat:@"%ld.jpg",i];
[_imgs addObject:imgName];
}
}
return _imgs;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(@"%@",self.imgs);
}
// 点击手势
- (IBAction)tapView:(UITapGestureRecognizer *)tap {
// 实现判断图片的左半边还是右半边点击
//获取触摸点
CGPoint point = [tap locationInView:tap.view];
NSLog(@"%@",NSStringFromCGPoint(point));
if (point.x <= tap.view.bounds.size.width * 0.5) {
NSLog(@"上一张");
[self previous];
}else{
NSLog(@"下一张");
[self next];
}
}
-(void)previous{
//判断当前图片是不是第一张
if(self.currentImgIndex == 0){
NSLog(@"已经是第一张");
return;
}
//减索引 改图片
self.currentImgIndex --;
self.imgView.image = [UIImage imageNamed:self.imgs[self.currentImgIndex]];
//转场动画
CATransition *animation = [CATransition animation];
animation.type = @"push";
//默认就是fromLeft
animation.subtype = @"fromLeft";
animation.duration = AnimationDuration;
[self.imgView.layer addAnimation:animation forKey:nil];
}
/**
* 提示:转场的动画的类型(type)和子头型(subtype) 能用字符串常量就用字符常量
*/
/**
*******************************************************
type:动画类型(比如:滴水效果,翻转效果...)
-------------------------------------------------------
fade kCATransitionFade 交叉淡化过渡
moveIn kCATransitionMoveIn 新视图移到旧视图上面
push kCATransitionPush 新视图把旧视图推出去
reveal kCATransitionReveal 将旧视图移开,显示下面的新视图
pageCurl 向上翻一页
pageUnCurl 向下翻一页
rippleEffect 滴水效果
suckEffect 收缩效果,如一块布被抽走
cube 立方体效果
oglFlip 上下左右翻转效果
rotate 旋转效果
cameraIrisHollowClose 相机镜头关上效果(不支持过渡方向)
cameraIrisHollowOpen 相机镜头打开效果(不支持过渡方向)
*******************************************************
subtype: 动画方向(比如说是从左边进入,还是从右边进入...)
------------------------------------------------------
kCATransitionFromRight;
kCATransitionFromLeft;
kCATransitionFromTop;
kCATransitionFromBottom;
当 type 为@"rotate"(旋转)的时候,它也有几个对应的 subtype,分别为:
90cw 逆时针旋转 90°
90ccw 顺时针旋转 90°
180cw 逆时针旋转 180°
180ccw 顺时针旋转 180°
**/
-(void)next{
//判断当前图片是不是最后一张
if (self.currentImgIndex == self.imgs.count - 1) {
NSLog(@"已经是最后一张");
return;
}
//加索引 改图片
self.currentImgIndex ++;
self.imgView.image = [UIImage imageNamed:self.imgs[self.currentImgIndex]];
//切换图片的时候,使用转场动画
CATransition *annimation = [CATransition animation];
//设置转场动画的类型
//`fade', 渐变
//`moveIn', `push' and `reveal'
annimation.type = @"rotate";
//设置转卖动画的子类型
// fromLeft', 动画由左边开始
// `fromRight', 动画由右边开始
//`fromTop' and
// * `fromBottom'
annimation.subtype = @"90cw";
annimation.duration = 3;
[self.imgView.layer addAnimation:annimation forKey:nil];
}
@end
CAAnimationGroup
<span style="font-size:18px;"> // 有一张图片,同时可以有平移、旋转、缩放的效果
// 实现这个效果 使用组动画[CAAnimationGroup]
//组动画怎么使用
//1.创建对象
CAAnimationGroup *group = [CAAnimationGroup animation];
//2.往里面添加多个动画
//2.1平移动画
CABasicAnimation *positionAni = [CABasicAnimation animation];
positionAni.keyPath = @"position";
positionAni.toValue = [NSValue valueWithCGPoint:CGPointMake(250, 250)];
//2.2旋转效果
CABasicAnimation *rotationAni = [CABasicAnimation animation];
rotationAni.keyPath = @"transform.rotation";
rotationAni.toValue = @(M_PI_2);
//2.3缩放效果
CABasicAnimation *scaleAni = [CABasicAnimation animation];
scaleAni.keyPath = @"transform.scale";
scaleAni.toValue = @(0.5);
group.duration = 3;
group.animations = @[positionAni,rotationAni,scaleAni];
//3.把组动画添加到图层上
[self.imgView.layer addAnimation:group forKey:nil];
</span>