iOS 核心动画介绍:
CAAnimation:核心动画的基础类,不能直接使用,负责动画运行时间、速度的控制,本身实现了CAMediaTiming协议。
CAPropertyAnimation:属性动画的基类(通过属性进行动画设置,注意是可动画属性),不能直接使用。
CAAnimationGroup:动画组,动画组是一种组合模式设计,可以通过动画组来进行所有动画行为的统一控制,组中所有动画效果可以并发执行。
CATransition:转场动画,主要通过滤镜进行动画效果设置。
CAKeyframeAnimation:关键帧动画,同样是通过属性进行动画参数控制,但是同基础动画不同的是它可以有多个状态控制。
CABasicAnimation:基础动画,通过属性修改进行动画参数控制,只有初始状态和结束状态。
CASpringAnimation : 弹簧动画 ,继承自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)
@interface ViewController ()
@property (nonatomic, strong) CALayer *myLayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
/**
* 动画 属性 配置
*/
[self animationSetup];
}
/**
* 动画 属性 配置
*/
- (void)animationSetup {
//创建layer 动画渲染 对象
CALayer *myLayer = [CALayer layer];
//设置layer的属性
myLayer.bounds = CGRectMake(0, 0, 50, 80);
myLayer.backgroundColor = [UIColor yellowColor].CGColor;
//CALayer 对象的 左上角的位置坐标
myLayer.position = CGPointMake(50, 50);
myLayer.anchorPoint = CGPointMake(0.5, 0.5);
myLayer.cornerRadius = 20;
//添加layer
[self.view.layer addSublayer:myLayer];
self.myLayer = myLayer;
}
彻底理解position与anchorPoint :
1、 anchorPoint:
一般都是先介绍position,再介绍anchorPoint。我这里反过来,先来说说anchorPoint。
从一个例子开始入手吧,想象一下,把一张A4白纸用图钉订在书桌上,如果订得不是很紧的话,白纸就可以沿顺时针或逆时针方向围绕图钉旋转,这时候图钉就 起着支点的作用。我们要解释的anchorPoint就相当于白纸上的图钉,它主要的作用就是用来作为变换的支点,旋转就是一种变换,类似的还有平移、缩 放。
继续扩展,很明显,白纸的旋转形态随图钉的位置不同而不同,图钉订在白纸的正中间与左上角时分别造就了两种旋转形态,这是由图钉 (anchorPoint)的位置决定的。如何衡量图钉(anchorPoint)在白纸中的位置呢?在iOS中,anchorPoint点的值是用一种 相对bounds的比例值来确定的,在白纸的左上角、右下角,anchorPoint分为为(0,0), (1, 1),也就是说anchorPoint是在单元坐标空间(同时也是左手坐标系)中定义的。类似地,可以得出在白纸的中心点、左下角和右上角的 anchorPoint为(0.5,0.5), (0,1), (1,0)。
像UIView有superView与subView的概念一样,CALayer也有superLayer与layer的概念,前面说到的白纸和图中的 矩形可以理解为layer,书桌和图中矩形以外的坐标系可以理解成superLayer。如果各自以左上角为原点,则在图中有相对的两个坐标空间。
2、 position:
这时候可以大胆猜测一下,position是不是就是anchorPoint在superLayer中的位置呢?答案是确定的,更确切地 说,position是layer中的anchorPoint点在superLayer中的位置坐标。因此可以说, position点是相对suerLayer的,anchorPoint点是相对layer的,两者是相对不同的坐标空间的一个重合点。
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//平移 动画
// [self translation];
//平移补充
//[self supplementTranslation];
//缩放动画
//[self zoom];
//旋转 动画
[self rotation];
}
/**
* 平移 动画
*/
- (void)translation {
//1.创建基础动画
//CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:<#(NSString *)#>]
CABasicAnimation *anima = [CABasicAnimation animation];
//1.1告诉系统要执行什么样的动画
anima.keyPath = @"position";
//设置通过动画,将layer从哪儿移动到哪儿
anima.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
anima.toValue = [NSValue valueWithCGPoint:CGPointMake(200, 300)];
//1.2设置动画执行完毕之后不删除
anima.removedOnCompletion = NO;
//1.3设置保存动画的最新状态
anima.fillMode = kCAFillModeForwards;
//removedOnCompletion、fillMode为了保持动画执行后的状态,否则动画自动移除 返回的最初的状态
//设置代理:设置动画的代理,可以监听动画的执行过程,这里设置控制器为代理。
anima.delegate = self;
NSString *str=NSStringFromCGPoint(self.myLayer.position);
NSLog(@"执行前:%@",str);
//2.添加核心动画到layer
[self.myLayer addAnimation:anima forKey:nil];
}
- (void)animationDidStart:(CAAnimation *)anim {
NSLog(@"开始执行动画");
}
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
NSString *str = NSStringFromCGPoint(self.myLayer.position);
NSLog(@"执行后:%@",str);
}
/**
* 平移补充
*/
- (void)supplementTranslation {
//1.创建动画
CABasicAnimation *anima = [CABasicAnimation animation];
anima.keyPath = @"transform";
//1.1设置动画执行时间
anima.duration = 2.0;
//1.2修改属性,执行动画
anima.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeTranslation(100, 100, 100)];
//1.3设置动画执行完毕后不删除动画
anima.removedOnCompletion = NO;
//1.4设置保存动画的最新状态
anima.fillMode = kCAFillModeForwards;
//2.添加动画到layer
[self.myLayer addAnimation:anima forKey:nil];
}
/**
* 缩放 动画
*/
- (void)zoom {
//1.创建动画
CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"bounds"];
//1.1设置动画执行时间
anima.duration = 2.0;
//1.2设置动画执行完毕不删除动画
anima.removedOnCompletion = NO;
//1.3设置保存动画的最新状态
anima.fillMode = kCAFillModeForwards;
//1.4修改属性,执行动画
anima.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
//2.添加动画到layer
[self.myLayer addAnimation:anima forKey:nil];
}
/**
* 旋转 动画
*/
- (void)rotation {
//1.创建动画
CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"transform"];
//1.1设置动画执行的时间
anima.duration = 2.0;
//1.2修改属性,执行动画
anima.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2 + M_PI_4, 0, 0, 1)];
//1.3设置动画执行完成完毕后不删除动画
anima.removedOnCompletion = NO;
//1.4设置保存动画的最新状态
// anima.fillMode = kCAFillModeForwards;
//2.添加动画到layer
[self.myLayer addAnimation:anima forKey:nil];
}
CASpringAnimation 弹簧动画:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self.label.layer removeAnimationForKey:@"position.x"];
CASpringAnimation *spring = [[CASpringAnimation alloc] init];
spring.keyPath = @"position.x";
//质量,影响图层运动时的弹簧惯性,质量越大,弹簧拉伸和压缩的幅度越大
spring.mass = 1;
//刚度系数(劲度系数/弹性系数),刚度系数越大,形变产生的力就越大,运动越快
spring.stiffness = 100;
//阻尼系数,阻止弹簧伸缩的系数,阻尼系数越大,停止越快
spring.damping = 5;
//初始速率,动画视图的初始速度大小
spring.initialVelocity = 0;
//结算时间 返回弹簧动画到停止时的估算时间,根据当前的动画参数估算
NSValue *fromValue = [NSValue valueWithCGPoint:CGPointMake(self.label.layer.position.x, self.label.layer.position.y)];
spring.fromValue = fromValue;
NSValue *toValue = [NSValue valueWithCGPoint:CGPointMake(self.label.layer.position.x + 60, self.label.layer.position.y)];
spring.toValue = toValue;
spring.duration = spring.settlingDuration;
[self.label.layer addAnimation:spring forKey:spring.keyPath];
}