Core Animation
简单介绍
1. Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍。也就是说,使用少量的代码就可以实现非常强大的功能。
2. Core Animation是跨平台的,可以用在Mac OS X和iOS平台。
3. Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。不阻塞主线程,可以理解为在执行动画的时候还能点击(按钮)。
要注意的是,Core Animation是直接作用在CALayer上的,并非UIView。
CAAnimation
- CAAnimation 所有动画的父类,基类(不能直接使用)。
- CAPropertyAnimation 属性动画,通过属性值的改变 产生动画效果,基类(不能直接使用)。
- CABasicAnimation 基础动画 -> 只能是两个点之间的变化。
- CASpringAnimation 弹簧动画。
- CAKeyframeAnimation 关键帧动画 -> 可以添加多个点的变化 或者 添加路径。
- CAAnimationGroup 动画组,可以同时添加多种动画,达到预期效果。
- CATransition 转场动画 -> 给视图切换的时候 添加动画效果。
- CALayer 图层(动画都是基于图层)只能显示内容,不能跟用户响应,发生改变,自图层不会发生改变,当改变属性值的时候,他本身自带动画效果,这种动画效果较做隐式动画。
CALayer常用属性
- bounds:边境范围
- position:中心点
- zPosition:z轴中心点
- anchorPoint:锚点 ✮✮✮✮✮
- anchorPointZ:Z轴锚点
默认锚点是与中心点重合锚点最小值是0,0 最大值是1,1;默认值:0.5,0.5;当视图改变的时候,是以锚点为基准去改变。
锚点的值与位置:
0,0 = 在图层的左上角
0,1 左下角
1,0 右上角
1,1 右下角
锚点值 = 锚点在视图上的位置.x.y/视图的宽高
- anchorPointZ:Z轴锚点
- transform 转换形态
- frame NO. Animatable 坐标
- hidden 隐藏
- doubleSided 图层背面是否显示
- geometryFlipped 翻转 颠倒
- masksToBounds 裁切边境
- contents 内容
- opaque 不透明度
- opacity 不透明度
- allowsEdgeAntialiasing 是否使用 变形后的抗锯齿
- backgroundColor 背景颜色
- borderWidth 边框宽
- borderColor 边框颜色
- shadowColor 阴影颜色
- shadowOpacity 阴影不透明度
- rasterizationScale 防止Retina屏幕像素化
- shadowOffset 阴影偏移量
- shadowRadius 阴影的半径
CALayer与UIView的关系
在iOS当中,所有的视图都从一个叫做UIVIew的基类派生而来,UIView可以处理触摸事件,可以支持基于Core Graphics绘图,可以做仿射变换(例如旋转或者缩放),或者简单的类似于滑动或者渐变的动画
CALayer类在概念上和UIView类似,同样也是一些被层级关系树管理的矩形块,同样也可以包含一些内容(像图片,文本或者背景色),管理子图层的位置。它们有一些方法和属性用来做动画和变换。和UIView最大的不同是CALayer不处理用户的交互。CALayer并不清楚具体的响应链(iOS通过视图层级关系用来传送触摸事件的机制),于是它并不能够响应事件,即使它提供了一些方法来判断是否一个触点在图层的范围之内。
也就是说,UIView视图,可以跟用户交互->rootLayer没有动画效果
CALayer 不可以跟用户交互 只能显示内容
UIView ->rootLayer发生改变,子图层也会发生改变
CALayer发生改变,子图层不会跟随发生改变
UIView与CALayer同级存在的意义
是要做职责分离,这样也能避免很多重复代码。在iOS和Mac OS两个平台上,事件和用户交互有很多地方的不同,基于多点触控的用户界面和基于鼠标键盘有着本质的区别,这就是为什么iOS有UIKit和UIView,但是Mac OS有AppKit和NSView的原因。他们功能上很相似,但是在实现上有着显著的区别。
绘图,布局和动画,相比之下就是类似Mac笔记本和桌面系列一样应用于iPhone和iPad触屏的概念。把这种功能的逻辑分开并应用到独立的Core Animation框架,苹果就能够在iOS和Mac OS之间共享代码,使得对苹果自己的OS开发团队和第三方开发者去开发两个平台的应用更加便捷。
CAAnimation子类
- CAPropertyAnimation:属性动画。也是基类,不可以直接使用,通过属性值的改变产生动画效果。
- CABaseAnimation:基础动画。只能两个点之间的变化(平移视图)。
- CAKeyframeAnimation:关键帧动画。可以添加多个点的变化或路径。
- CAAnimationGRoup:动画组。可以添加多种动画达到预期的效果。
- CATransition:转场动画。给视图切换的时候添加动画效果
基础动画
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可看做是最多只有两个关键帧的CAKeyframeAnimation
在关键帧动画中还有一个非常重要的参数,那便是calculationMode:计算模式。其主要针对的是每一帧的内容为一个座标点的情况,也就是对anchorPoint 和 position 进行的动画。当在平面座标系中有多个离散的点的时候,可以是离散的,也可以直线相连后进行插值计算,也可以使用圆滑的曲线将他们相连后进行插值计算。
calculationMode目前提供如下几种模式:
kCAAnimationLinear calculationMode的默认值,表示当关键帧为座标点的时候,关键帧之间直接直线相连进行插值计算;
kCAAnimationDiscrete 离散的,就是不进行插值计算,所有关键帧直接逐个进行显示;
kCAAnimationPaced 使得动画均匀进行,而不是按keyTimes设置的或者按关键帧平分时间,此时keyTimes和timingFunctions无效;
- kCAAnimationCubic 对关键帧为座标点的关键帧进行圆滑曲线相连后插值计算,这里的主要目的是使得运行的轨迹变得圆滑;
kCAAnimationCubicPaced 看这个名字就知道和kCAAnimationCubic有一定联系,其实就是在kCAAnimationCubic的基础上使得动画运行变得均匀,就是系统时间内运动的距离相同,此时keyTimes以及timingFunctions也是无效的。
动画组
CAAnimationGroup
CAAnimation的子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行.
属性:
- animations:用来保存一组动画对象的NSArray。默认情况下,一组动画对象是同时运行的,也可以通过设置动画对象的beginTime属性来更改动画的开始时间.
转场动画
CATransition
CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。iOS比Mac OS X的转场动画效果少一点。
UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果.
属性:
type:动画过渡类型
subtype:动画过渡方向
startProgress:动画起点(在整体动画的百分比)
endProgress:动画终点(在整体动画的百分比)
#import "ViewController.h"
#define Angle(a) (a)*M_PI/180
#define sAngle 6 //每秒旋转多少度:sAngle*N秒*M_PI/180
@interface ViewController (){
CALayer *layer;
}
@property (nonatomic,strong)CALayer *pointLayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 初始化CAlayer
layer = [CALayer layer];
layer.frame = CGRectMake(100, 100, 100, 100);
// 设置图层拐角
layer.cornerRadius = 100/2;
layer.backgroundColor =[UIColor brownColor].CGColor;
// 添加到父图层
[self.view.layer addSublayer:layer];
// NSLog(@"%@",self.pointLayer);
_pointLayer.anchorPoint =CGPointMake(0, 0.5);
// 放置一张图片
// 图层上 要的是颜色(CGColorRef) 图片(CGImageRef)的 数据,而非UI
_pointLayer.contents =(id)[UIImage imageNamed:@"shizhen.png"].CGImage;
self.pointLayer.anchorPoint = CGPointMake(0.5, 0.9);
[self star];
[NSTimer scheduledTimerWithTimeInterval:1
target:self selector:@selector(star) userInfo:nil repeats:YES];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
// 获得点击触摸的点
layer.position =[[touches anyObject] locationInView:self.view];
CGFloat width =CGRectGetWidth(layer.bounds)!=100?100:50;
// 通过获得的点 改变尺寸
layer.bounds =CGRectMake(0, 0, width, width);
// 改变颜色
CGColorRef color = [UIColor brownColor].CGColor != layer.backgroundColor ?
[UIColor brownColor].CGColor:
[UIColor colorWithRed:0.863
green:0.634
blue:0.490
alpha:1.000].CGColor;
layer.backgroundColor = color;
// 改变半径
layer.cornerRadius =width!=100?0:width/2;
// 改变透明度
layer.opacity = 0.3;
// 设置锚点,最大值是1,最小值是0
// _pointLayer.transform = CATransform3DMakeRotation(/*弧度*/Angle(60),0 , 0, 1);
}
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
layer.opacity = 1.0;
// 还原
// _pointLayer.transform = CATransform3DIdentity;
}
//利用懒加载 创建一个layer
-(CALayer *)pointLayer{
if (_pointLayer) {
return _pointLayer;
}
_pointLayer = [CALayer layer];
_pointLayer.bounds =CGRectMake(0, 0, 18, 220);
//设置中心点
_pointLayer.position =self.view.center;
_pointLayer.backgroundColor =
[UIColor colorWithRed:1.000
green:0.392
blue:0.929
alpha:1.000].CGColor;
[self.view.layer addSublayer:_pointLayer];
return _pointLayer;
}
-(void)star{
// NSCalendar 日历;可以获得年月日 时分秒,都是NSCalendar上的组件
// NSDateComponents
// 获得当前日历
NSCalendar *calender =[NSCalendar currentCalendar];
NSDateComponents *componest =[calender components:
NSCalendarUnitHour|
NSCalendarUnitMinute|
NSCalendarUnitSecond fromDate:[NSDate date]];
float s = componest.second * sAngle;
_pointLayer.transform = CATransform3DMakeRotation(/*弧度*/Angle(s),0 , 0, 1);
}
@end