相关文献:
iOS CoreAnimation(一) - 基础知识
iOS CoreAnimation(二) - CALayer/UIBezierPath
iOS CoreAnimation(三) - CAEmitterLayer粒子图层
本文主要内容:
1.了解CoreAnimation
2.UIView与CALayer
3.图层树/表示树/渲染树
4.hitTest
5.了解核心动画类的属性
6.核心动画KeyPath表
一、了解CoreAnimation
CPU(Central Processing Unit-中央处理器)
是一块超大规模的集成电路,是一台计算机的运算核心(Core)和控制核心( Control Unit)。它由运算器(ALU)和控制器(CU)两大部件组成。此外,还有若干个寄存器和高速缓冲存储器及实现它们之间联系的数据、控制及状态总线。CPU的功能主要是解释计算机指令以及处理计算机软件中的数据。
GPU(Graphics Processing Unit-图形处理器)
;又称显示核心、显卡、视觉处理器、显示芯片或绘图芯片)是一种专门在个人电脑、工作站、游戏机和一些移动设备(如平板电脑、智能手机等)上图像运算工作的微处理器。GPU不仅在图像处理中应用广泛,还在科学计算、密码破解、数值分析、大数据处理、金融分析等需要并行运算的领域中广为应用。
CoreAnimation
是对OpenGL/Metal 与 CoreGraphics进行封装的专门处理图形的一套API接口,简化了图形图像处理需要大量的计算以节约开发者的开发时间。其底层就是让GPU去做事情。
CAAnimation
是所有动画对象的父类(抽象类,虚类),实现CAMediaTiming
协议,负责控制动画的时间、速度和时间曲线等等,是一个抽象类,不能直接使用。
-
CAAnimationGroup
: 动画组,可以将很多种动画合并到一起,组成动画效果。 -
CATransition
: 转场动画效果。 -
CAKeyframeAnimation
: 关键帧动画效果。values
: 一个NSArray
对象。里面的元素称为”关键帧”
(keyframe
),动画对象会在指定的时间(duration
)内,依次显示values
数组中的每一个关键帧。简单理解为,很多动画帧执行。 -
CABasicAnimation
: 基础动画,简单常见的动画效果。 -
CASpringAnimation
: iOS9.0之后新增,弹簧效果的动画,是CABasicAnimation
的子类。
二、UIView与CALayer(视图和图层)
1.UIView与CALayer的关系:
- 1.UIView是UIKit框架中的, 继承于UIRespond,
View可以响应触摸事件
;
CALayer是QuartzCore框架里面CoreAnimation中的,继承自NSObject,Layer不响应事件
。 - 2.UIView有个只读的layer属性,称为根Layer,
UIView的图层是由layer来生成的
,所以对UIView的frame等属性的修改本质上是对layer的属性的修改。 - 3.可以给UIView添加子Sublayer,[self.layer addSublayer:],效果像addSubview一样显示,但sublayer在修改position、size、opacity等属性时会产生隐式动画(默认有个动画效果), 这就没有操作subview方便。
- 4.使用系统提供的layer和自定义layer都可添加为subLayer,但需要调用[layer setNeedsDisplay]。 对于自定义layer方式有三个:设置layer代理、自定义CALayer子类。
- 5.UIView是根layer的代理。
分工明确:view去相应事件;layer去做显示。
2.了解UIView和CALayer的属性
值得注意的是:
- 1.在
CALayer
中很少使用frame
属性,因为frame
本身不支持动画效果,通常使用bounds
和position
代替 - 2.
CALayer
中透明度使用opacity
表示而不是alpha
;中心点使用position
而不是center
- 3.
anchorPoint
属性是图层的锚点,范围在(0-1,0-1)表示在x、y轴的比例,这个点永远可以同position
(中心点)重合,当图层中心点固定后,调整anchorPoint
。即可达到调整图层显示位置的作用(因为它永远和position重合)
position
和anchorPoint
在图层中的关系:
anchorPoint
的默认值为(0.5,0.5),也就是anchorPoint
默认在layer
的中心点。
默认情况下,使用addSublayer
函数添加layer
时,如果已知layer
的frame
值,根据上面的结论,那么position
的值便可以用下面的公式计算:
position.x = frame.origin.x + anchorPoint.x * bounds.size.width;
position.y = frame.origin.y + anchorPoint.y * bounds.size.height;
三、图层树/表示树/渲染树 (Layer Tree / Presentation Tree / Render Tree)
图层树(Layer Tree):包含每一层图层里面对象模型的值(开发者设置的一些值)。
表示树(呈现树Presentation Tree):比如当前动画要发生了,它就包含了当前动画将要显示的值。比如一个layer需要改变颜色,它不会立马更新(隐式动画),需要等待图层树完了之后,表示树才会更新出来。
所以图层树与表示树之间会有一个滞后性。
- 渲染树(Render Tree):它使用的是表示树的值,主要对独立的UI渲染动作,每一次渲染都是单独的线程来做事。
LayerTree -> PresentationTree滞后性的案例:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// 平移动画
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"position.y";
animation.toValue = @600;
animation.duration = 1;
[_redView.layer addAnimation:animation forKey:nil];
}
执行动画平移完了之后发现redView回到初始的位置。
解决动画恢复到初始位置:
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
/**
KCAFil1ModeForwards:动画结束后,1ayer会一直保持动画最后的状态
KCAFi11ModeBackwards:在动画开始前,将动画加入一个Layer, layer便立即进入动画的初始状态井等待动画开始.(设置之后就显示动画第一帧)
kCAFillModeBoth: kCAFillModeForwards & kCAFillModeBackwards
kCAFil1ModeRemoved: 默认,
*/
四、hitTest
layer的hitTest
view的hitTest
#import "RedView.h"
@implementation RedView
/**
- (UIview*)hitTest: (CGPoint )point withEvent: (UIEvent *)event
point:在接收器局部坐标系中的点
event:系统保证调用此方法事简。
Hit Test 调用顺序
touch -> UIApplication -> UIWindow -> UIViewController -> UIView -> subview ->... -> 合适的View
事件的传递顺序刚好和与之相反。
常见UIview 不响应事件的处理有那些?
1.view.userInteractionEnabled = NO:
2.view.hidden = yes;
3.view.alpha < 0.05:
4. view #BitsuperViewtibounds
*/
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
// 1.是否相应时间的必然条件
if (self.userInteractionEnabled == NO || self.alpha < 0.05 || self.hidden == YES) {
return nil;
}
// 2,touch的point在self.bounds内容
if ([self pointInside:point withEvent:event]) {
for(UIView *subview in self.subviews) {
// 进行坐标转换
CGPoint coverPoint = [subview convertPoint: point fromView:self];
UIView *hittestView = [subview hitTest:coverPoint withEvent:event];
if (hittestView) {return hittestView;}
}
return self;
}
return nil;
}
@end
注意:常见UIview不响应事件的处理有那些?
1.view.userInteractionEnabled = NO:
2.view.hidden = YES;
3.view.alpha < 0.05:
4.超出view边界不响应
HitTest运用场景:
五、CoreAnimation简单使用
- CABasicAnimation
#import "ViewController.h"
/*
动画添加步骤:
1.找演员CALayer,确定动画主角
2.写剧本CAAnimation,规定动画怎么样变换
3.开拍AddAnimation,开始执行
*/
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *redView;
@property (nonatomic,strong) CALayer *layer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
CALayer *layer = [CALayer layer];
layer.frame = CGRectMake(100, 100, 100, 100);
layer.backgroundColor = [UIColor greenColor].CGColor;
_layer = layer;
[self.view.layer addSublayer:layer];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//动画1
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"position.y";
animation.toValue = @600;
animation.duration = 1;
//解决动画恢复到初始位置
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[_redView.layer addAnimation:animation forKey:nil];
//动画2
//begin a new transaction
[CATransaction begin];
//set the animation duration to 1 second
[CATransaction setAnimationDuration:2.0];
_layer.backgroundColor = [UIColor orangeColor].CGColor;
[CATransaction setCompletionBlock:^{
//rotate the layer 90 degrees
CGAffineTransform transform = self.layer.affineTransform;
transform = CGAffineTransformRotate(transform, M_PI_2);
self.layer.affineTransform = transform;
}];
//commit the transaction
[CATransaction commit];
}
- CAKeyframeAnimation
#import "ViewController.h"
#define angleToRadians(angle) ((angle)/180.0 * M_PI) // 度数转弧度
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *pigView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// 图片抖动
CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
anim.keyPath = @"transform.rotation";
anim.values = @[@angleToRadians(-3),
@angleToRadians(5),
@angleToRadians(-3),
];
anim.autoreverses = YES;
anim.speed = 2;
anim.duration = 1;
anim.repeatCount = MAXFLOAT;
[_pigView.layer addAnimation:anim forKey:nil];
}
@end
六、了解核心动画类的属性
1.CAMediaTiming
协议
不只是CAAnimation遵循CAMediaTiming协议,CALayer也遵循这个协议,所有在一定程度上我们可以通过控制layer本身的协议属性来控制动画节奏。
CAMediaTiming
协议中定义了时间,速度,重复次数等。属性定义如下:
beginTime
-> 用来设置动画延时,若想延迟1秒,就设置为CACurrentMediaTime()+1
,其中CACurrentMediaTime()
为图层当前时间。duration
-> 动画的持续时间。speed
-> 动画速率,决定动画时间的倍率。当speed为2时,动画时间为设置的duration*0.5
。timeOffset
-> 动画时间偏移量。比如设置动画时长为3秒,当设置timeOffset
为1.5时,当前动画会从中间位置开始,并在到达指定位置时,走完之前跳过的前半段动画。repeatCount
-> 动画的重复次数。repeatDuration
-> 动画的重复时间。autoreverses
-> 动画由初始值到最终值后,是否反过来回到初始值的动画。如果设置为YES,就意味着动画完成后会以动画的形式回到初始值。fillMode
-> 决定当前对象在非动画时间段的行为.比如动画开始之前,动画结束之后。
fillMode详细说明
:试想这样一个问题:在beginTime非0(即动画未真正执行之前),以及removeOnCompletion被设置为NO的动画结束时,我们会遇到这样一个问题:被设置动画的属性应该是什么值?
一种可能是属性与动画没被添加之前保持一致,还有一种可能是保持动画开始之前那一帧或者动画结束那一帧,这就是所谓的填充。
CAMediaTiming的fillMode用来控制填充效果,它是一个NSString类型,有四种常量可供使用:
kCAFillModeRemoved (default)
,动画开始前和结束后,动画对图层都没有影响,图层依然保持初始值;
kCAFillModeForwards
动画结束后,图层一直保持动画后的最终状态;
kCAFillModeBackwards
动画开始前,只要加入动画就会处于动画的初始状态;
kCAFillModeBoth
综合了kCAFillModeForwards与kCAFillModeBackwards特性。
(动画加入图层到真正执行动画的时间段里,图层保持动画初始状态;动画结束之后保持动画最终状态)
2.CAAnimation
基础类
CAAnimation
核心动画基础类,不能直接使用。遵循了CAMediaTiming
协议,增加了CAAnimationDelegate
的代理属性等。关于它的定义如下:
@interface CAAnimation : NSObject<NSSecureCoding, NSCopying, CAMediaTiming, CAAction>
@property(nullable, strong) CAMediaTimingFunction *timingFunction;
@property(nullable, strong) id <CAAnimationDelegate> delegate;
@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;
@end
removedOnCompletion
-> 是否让图层保持显示动画执行后的状态,默认为YES,也就是动画执行完毕后从涂层上移除,恢复到执行前的状态,如果设置为NO,并且设置fillMode为kCAFillModeForwards,则保持动画执行后的状态。delegate
-> 代理。timingFunction
-> 控制动画的节奏、动画缓冲属性。动画实际上就是在一段时间内随着某个特定速率执行变化的过程,现实中的任何物体都会在运动中经历加速或者减速的过程,而不是速度骤变;因此,CoreAnimation也内嵌了一系列标准的缓冲函数来使动画看起来更平滑自然,这就是我们要说到的动画缓冲。
timingFunction的值:
kCAMediaTimingFunctionLinear
默认,匀速执行动
kCAMediaTimingFunctionEaseIn
慢进快出
kCAMediaTimingFunctionEaseOut
快进慢出
kCAMediaTimingFunctionEaseInEaseOut
慢进慢出,中间加速
kCAMediaTimingFunctionDefault
默认.
当然也可通过自定义创建CAMediaTimingFunction。
CAAnimation的delegate代理方法如下几个:
//动画开始时执行的回调
- (void)animationDidStart:(CAAnimation *)anim;
//动画结束后执行的回调
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
3.CAPropertyAnimation
属性动画
CAPropertyAnimation
是一个抽象类,不可直接使用。不能直接用于实现CALayer
动画操作,但是它的类定义中增加用于设置CALayer
可被实现动画的属性keyPath
。
+ (instancetype)animationWithKeyPath:(NSString *)path;
该方法仅需要一个参数,该参数只是一个字符串的值,指定CALayer
的动画属性名,该设置属性动画控制CALayer
的哪个动画属性持续的改变。
CAPropertyAnimation属性
具体如下:
keyPath
-> CALayer的某个属性名,并通过这个属性的值进行修改,达到相应的动画效果。additive
-> 属性动画是否以当前动画效果为基础,默认为NO。cumulative
-> 指定动画是否为累加效果,默认为NO。valueFunction
-> 此属性配合CALayer的transform属性使用。affineTransform
-> CGAffineTransform对象(变换矩阵),该对象代表CALayer执行X,Y两个维度(也就是平面)上的旋转,缩放,位移,斜切,镜像等变换矩阵。transform
-> 该属性值指定一个CATransform3D对象,该对象代表对CALayer执行X,Y,Z三个维度(三维空间)中的旋转,缩放,位移,斜切,镜像等变换矩阵。很明显如果只是对CALayer进行平面
上的变换,指定普通的affineTransform
属性即可,如果要对CALayer执行三维
空间的变化,则需要指定transform
属性。关于变形矩阵我的文章里有介绍CALayer中仿射变换。
CABasicAnimation基础动画,通过keyPath对应属性进行控制,需要设置fromValue以及toValue。添加属性如下:
fromValue -> keyPath相应属性的初始值。
toValue -> keyPath相应属性的结束值。
byValue -> 在不设置toValue时,toValue = fromValue + byValue,也就是在当前的位置上增加多少。
4.CAAnimationGroup
动画组
能将多个动画组合在一起,如平移、缩放、旋转等效果组合在一起做出更炫酷的的效果。
animations
-> 所有动画效果元素的数组。
NSLog(@"动画执行前redView.frame:%@", NSStringFromCGRect(self.redView.frame));
//平移
CABasicAnimation *transition = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
transition.toValue = @(300);
//旋转
CABasicAnimation *rotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
rotation.toValue = @(M_PI);
//缩放
CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scale.toValue = @(0.2);
//添加组动画
CAAnimationGroup *group = [CAAnimationGroup animation];
//注意这里动画的效果 要设置成group的
group.duration = 2.0;
group.animations = @[rotation, scale, transition];
group.removedOnCompletion = NO;
group.fillMode = kCAFillModeForwards;
[self.redView.layer addAnimation:group forKey:nil];
5.CABasicAnimation基础动画
CABasicAnimation
即基础动画,在指定可动画属性后,动画会按照预定的参数持续一定时间由初始值变换为终点值。
其实CABasicAnimation
就相当于只有开始和结束两个帧的特殊关键帧动画。
CABasicAnimation的属性:
CABasicAnimation继承链条:CABasicAnimation-> CAPropertyAnimation -> CAAnimation -> NSObject && 遵循CAMediaTiming协议
fromValue
-> 起始值toValue
-> 结束值byValue
-> keyPath属性的变化值
CABasicAnimation
的简单使用:
@interface TestBacicAnimation1VC ()<CAAnimationDelegate>
@property (nonatomic,strong) CALayer *colorLayer;
@end
@implementation TestBacicAnimation1VC
- (void)viewDidLoad {
[super viewDidLoad];
//创建显示颜色的图层,添加于视图控制器的View上
CALayer *colorLayer = [CALayer layer];
colorLayer.frame = CGRectMake(50, 50, 100, 100);
colorLayer.backgroundColor = [UIColor redColor].CGColor;
self.colorLayer = colorLayer;
[self.view.layer addSublayer:colorLayer];
}
- (IBAction)changeColor:(UIButton *)sender{
//步骤1:创建动画
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"backgroundColor";
//步骤2:设定动画属性
animation.autoreverses = NO;
animation.duration = 0.25;
animation.repeatCount = 1;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.delegate = self;
UIColor *randomColor = [UIColor randomColor]; //自定义获取随机色的方法
animation.toValue = (__bridge id _Nullable)(randomColor.CGColor);
//步骤3:添加动画到图层
[self.colorLayer addAnimation:animation forKey:@"keyPath_backgroundColor"];
}
- (void)animationDidStop:(CABasicAnimation *)anim finished:(BOOL)flag{
//禁用隐式动画
[CATransaction begin];
[CATransaction setDisableActions:true];
self.colorLayer.backgroundColor = (__bridge CGColorRef)anim.toValue;
[CATransaction commit];
}
关闭隐式动画:
对独立图层(即非UIView的关联图层,类似上述例子中的colorLayer)做更新属性的显式动画,我们需要设置一个事务来禁用图层行为,否则动画会发生两次,一次是因为显式的CABasicAnimation,另一次是因为隐式动画,从而导致我们看到的动画异常。
6.CAKeyframeAnimation
关键帧动画
CAKeyframeAnimation 关键帧动画,同样通过·keyPath·对应属性进行控制,但它可以通过·values·或者·path·进行多个阶段的控制。
CAKeyframeAnimation
属性如下:
CAKeyframeAnimation继承链条:CAKeyframeAnimation-> CAPropertyAnimation -> CAAnimation -> NSObject && 遵循CAMediaTiming协议
values
-> 关键帧组成的数组,动画会依次显示其中的每一帧。path
-> 关键帧路径,动画进行的要素,优先级比values
高,但是只对CALayer
的anchorPoint
和position
起作用。(如果你设置了path,那么values将被忽略)keyTimes
-> 每一帧对应的时间,如果不设置,则各关键帧平分设定时间。timingFunctions
-> 每一帧对应的动画节奏。calculationMode
-> 动画的计算模式,系统提供了对应的几种模式。tensionValues
-> 动画张力控制。continuityValues
-> 动画连续性控制。biasValues
-> 动画偏差率控制。rotationMode
-> 动画沿路径旋转方式,系统提供了两种模式。
关键帧动画的实现方式实际分为两种:
1.通过values设置关键帧属性值数组;
2.通过path设置关键帧路径,而且此种方式的优先级较高;
- 通过
values
设置关键帧
实现这样的关键帧动画:创建一个紫色滑块在四个坐标点之间滑动;具体的代码实现如下:
- (void)viewDidLoad {
[super viewDidLoad];
//创建测试帧动画的紫色图层
UIView *purpleView = [UIView new];
purpleView.frame = CGRectMake(0, 0, 50, 50);
purpleView.center = CGPointMake(50, 100);
purpleView.backgroundColor = [UIColor purpleColor];
[self.view addSubview:purpleView];
//步骤1:创建动画
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position";
//步骤2:设置动画关键帧数据
NSValue *value1 = [NSValue valueWithCGPoint:CGPointMake(50, 100)];
NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(kDeviceWidth -50, 100)];
NSValue *value3 = [NSValue valueWithCGPoint:CGPointMake(kDeviceWidth -50, kDeviceWidth- 100)];
NSValue *value4 = [NSValue valueWithCGPoint:CGPointMake(50, kDeviceWidth -100)];
NSValue *value5 = [NSValue valueWithCGPoint:CGPointMake(50, 100)];
animation.values = @[value1,value2,value3,value4,value5];
//步骤3:设定动画属性
animation.repeatCount = MAXFLOAT; //重复执行
animation.autoreverses = NO;
animation.removedOnCompletion = NO;
animation.duration = 4;
//animation.keyTimes = @[@(0), @(1 / 10.0), @(5 / 10.0), @(9 / 10.0), @(1) ];
animation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[purpleView.layer addAnimation:animation forKey:nil];
}
- 过
path
设置关键帧路径
实现🚗沿着轨道行走的动画:
/*
贝塞尔曲线:1.数据点(起点终点);2.控制点
*/
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self test];
}
- (void)test{
//1.定义贝塞尔曲线
UIBezierPath *path = [UIBezierPath bezierPath];
//起始点
[path moveToPoint:CGPointMake(20, 200)];
//终点 和 控制点
[path addCurveToPoint:CGPointMake(300, 200) controlPoint1:CGPointMake(100, 100) controlPoint2:CGPointMake(200, 300)];
//2.为了显示贝塞尔曲线->shapeLayer(显示路径)
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = path.CGPath;
shapeLayer.fillColor = nil;
shapeLayer.strokeColor = [UIColor redColor].CGColor;
[self.view.layer addSublayer:shapeLayer];
//添加图层
CALayer *carLayer = [CALayer layer];
carLayer.frame = CGRectMake(15, 200-18,36,36);
//寄宿图
carLayer.contents = (id)[UIImage imageNamed:@"car.png"].CGImage;
carLayer.anchorPoint = CGPointMake(0.5, 0.8); // 锚点
[self.view.layer addSublayer:carLayer];
// 让轨道和🚗图层结合起来
//关键帧动画
CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
//路径! keypath
anim.keyPath = @"position";
//path
anim.path = path.CGPath;
anim.duration = 4.0;
anim.rotationMode = kCAAnimationRotateAuto;
anim.repeatCount = MAXFLOAT;
[carLayer addAnimation:anim forKey:nil];
}
@end
7.CATransition
转场动画
type
-> 转场动画类型。
kCATransitionFade:交叉淡化过渡
kCATransitionPush:新视图吧旧视图
kCATransitionMoveIn:新视图移到旧视图上面
kCATransitionReveal:将旧视图移开,显示下面的视图
用字符串表示:
pageCurl:向上翻页效果
pageUnCurl:向下翻页效果
cube:立方体翻滚效果
oglFlip:上下左右翻转效果
rippleEffect:波纹
suckEffect:吮吸
flipFromLeft:左翻转
flipFromRight:右翻转
suckEffect:收缩效果,如一块布被抽走
rippleEffect:水滴效果
cameraIrisHollowOpen:相机镜头打开效果
cameraIrisHollowClose:相机镜头关闭效果
subtype
-> 转场动画方向。
kCATransitionFromRight 从右向左,
kCATransitionFromTop 从上向下,
kCATransitionFromLeft 从左向右,
kCATransitionFromBottom 从下向上
startProgress
-> 动画起点进度(整体的百分比)。endProgress
-> 动画终点进度(整体的百分比)。filter
-> 自定义转场。duration
-> 动画执行时间timingFunction
-> 动画的运动轨迹,用于变化起点和终点之间的插值计算,形象点说它决定了动画运行的节奏,比如是均匀变化(相同时间变化量相同)还是先快后慢,先慢后快还是先慢再快再慢
kCAMediaTimingFunctionLinear 线性,即匀速
kCAMediaTimingFunctionEaseIn 先慢后快
kCAMediaTimingFunctionEaseOut 先快后慢
kCAMediaTimingFunctionEaseInEaseOut 先慢后快再慢
kCAMediaTimingFunctionDefault 实际效果是动画中间比较快
@interface TestTransition1VC ()
@property (nonatomic,strong) UIImageView *imageView;
@property (nonatomic,strong) NSArray *images;
@property (nonatomic, copy) NSString *type;
@property (nonatomic, copy) NSString *subtype;
@end
@implementation TestTransition1VC
- (void)viewDidLoad {
[super viewDidLoad];
self.images = @[[UIImage imageNamed:@"tree_spring"],
[UIImage imageNamed:@"tree_summer"],
[UIImage imageNamed:@"tree_autumn"],
[UIImage imageNamed:@"tree_winter"]];
self.type = kCATransitionFade;
self.subtype = kCATransitionFromRight;
}
- (void)perforomTransitionAnimation{
CATransition *transition = [[CATransition alloc] init];
transition.type = _type;
transition.subtype = _subtype;
transition.duration = 0.5;
[self.imageView.layer addAnimation:transition forKey:nil];
UIImage *currentImage = self.imageView.image;
NSUInteger index = [self.images indexOfObject:currentImage];
index = (index + 1) % self.images.count;
self.imageView.image = self.images[index];
}
7.CASpringAnimation
弹簧动画
CASpringAnimation弹簧动画,带有初始速度以及阻尼指数等物理参数的属性动画。
mass
-> 质量越大,弹簧拉伸和压缩的幅度越大,动画的速度变慢,并且波动幅度变大,影响图层运动时的弹簧惯性stiffness
-> 弹簧的劲度系数。刚度系数越大,形变产生的力就越大,运动越快damping
-> 阻尼系数,地面的摩擦力。阻尼系数越大,停止越快initialVelocity
-> 初始速度,相当于给小球一个初始速度(可正可负,方向不同),初始速率,动画视图的初始速度大小
速率为正数时,速度方向与运动方向一致,速率为负数时,速度方向与运动方向相反settlingDuration
-> 结算时间 返回弹簧动画到停止时的估算时间,根据当前的动画参数估算 通常弹簧动画的时间使用结算时间比较准确
self.animationView = [[UIView alloc]init];
self.animationView.frame = CGRectMake(0, kHeight/2-50, 50, 50);
self.animationView.backgroundColor = [UIColor greenColor];
[self.view addSubview:self.animationView];
//弹簧效果
CASpringAnimation *spring = [CASpringAnimation animationWithKeyPath:@"position.y"];
spring.fromValue = @150;
spring.toValue = @100;
//阻尼系数
spring.damping = 0.1;
//刚度系数: (劲度系数 / 弹性系数): 系数越大,形变的产生的力越大, 运动越快
spring.stiffness = 10;
//质量: 影响图层运动时候的惯性, 质量越大弹簧拉伸和压缩的幅度越大 (动画的幅度,波动变大)
spring.mass = 1;
//初识速率: 动画视图的初识速度大小
//速率为正时候, 速度方向与运动方向一致, 否则相仿.
spring.initialVelocity = 1;
// settlingDuration 结算时间,预估弹簧动画到停住的时间的估算, 根据当前动画的各个参数估算, 通常弹簧动画的估算时间使用结算时间比较准确
spring.duration = spring.settlingDuration;
[self.animationView.layer addAnimation:spring forKey:@"springAnimation"];
七、核心动画KeyPath表
- 1.CALayer
keyPath | 描述 |
---|---|
transform.rotation.x | 按x轴旋转的弧度 |
transform.rotation.y | 按y轴旋转的弧度 |
transform.rotation.z | 按z轴旋转的弧度 |
transform.scale | 按比例放大缩小 |
transform.scale.x | 在x轴按比例放大缩小 |
transform.scale.y | 在y轴按比例放大缩小 |
transform.scale.z | 在z轴按比例放大缩小 |
transform.translation | x,y 坐标均发生改变 |
transform.translation.x | 沿x轴平移 |
transform.translation.y | 沿y轴平移 |
transform.translation.z | 沿z轴平移 |
transform | CATransform3D 4*4矩阵 |
bounds | layer大小 |
frame | layer位置/大小 |
position | layer位置 |
anchorPoint | 锚点位置 |
cornerRadius | 圆角大小 |
zPosition | z轴位置 |
sublayers | 子layers |
sublayerTransform | 子layers的CATransform3D 4*4矩阵 |
filters | 滤镜 |
backgroundColor | 背景颜色 |
backgroundFilters | 背景滤镜 |
contents | Layer内容,呈现在背景颜色之上 |
contentsRect | Layer内容的Rect |
path | 路径 |
mask | 遮罩蒙版 |
masksToBounds | 是否显示超出边缘部分 |
doubleSided | 是否双面都渲染 |
borderColor | 描边颜色 |
borderWidth | 描边宽度 |
shadowColor | 阴影颜色 |
shadowOffset | 阴影偏移距离 |
shadowOpacity | 阴影透明度 |
shadowRadius | 阴影圆角 |
shadowPath | 阴影路径 |
opacity | 透明度 |
hidden | 是否隐藏 |
- 2.CAGradientLayer
keyPath | 描述 |
---|---|
colors | 颜色渐变 |
locations | 渐变位置 |
startPoint | 开始点 |
endPoint | 终止点 |
- 3.CAShapeLayer
keyPath | 描述 |
---|---|
fillColor | 填充颜色 |
strokeStart | 边框颜色开始,从无到有 |
strokeEnd | 边框颜色结束,从有到无 |
strokeColor | 路径颜色 |
lineWidth | 路径的线宽 |
miterLimit | 相交长度的最大值 |
lineDashPhase | 虚线样式 |
- 4.CAEmitterLayer
keyPath | 描述 |
---|---|
emitterPosition | 粒子发射器位置 |
emitterZPosition | 粒子发射器Z深度 |
emitterSize | 粒子发射器大小 |
- 5.CAReplicatorLayer
keyPath | 描述 |
---|---|
instanceDelay | - |
instanceTransform | - |
instanceRedOffset | - |
instanceGreenOffset | - |
instanceBlueOffset | - |
instanceAlphaOffset | - |
- 6.CATextLayer
keyPath | 描述 |
---|---|
fontSize | 字体大小 |
foregroundColor | 背景颜色 |
- 7.CATransform3D
keyPath | 描述 |
---|---|
rotation.x | - |
rotation.y | - |
rotation.z | - |
rotation | - |
scale.x | - |
scale.y | - |
scale.z | - |
scale | - |
translation.x | - |
translation.y | - |
translation.z | - |
- 8.CGPoint
keyPath | 描述 |
---|---|
x | - |
y | - |
- 9.CGSize
keyPath | 描述 |
---|---|
width | - |
height | - |
- 10.CGRect
keyPath | 描述 |
---|---|
origin | - |
origin.x | - |
origin.y | - |
size | - |
size.width | - |
size.height | - |