动画 Animation
CALayer是动画产生的地方,当将动画添加到Layer层的时候,不能直接修改layer的属性
- CoreAnimation 有两个Layer层次结构 - 模型层树(model layer tree)和表示层树(presentation layer tree)
- (instancetype)presentationLayer; - 表示层
- (instancetype)modelLayer; - 模型层
CAAnimation常用的有:
- CABasicAnimation
CABasicAnimation的常用属性:
- duration 动画的持续时间
- beginTime 指定动画开始的时间,从开始延迟几秒的话,设置为CACurrentMediaTime() + 秒数的方式
- repeatCount 动画的持续次数
- repeatDuration 设置动画的时间,在该时间内动画一直执行,不计次数
- autoreverses 动画结束时是否执行逆动画
- fillMode 动画在开始和结束时的动画,默认值是KCAFillModeRemoved
- kCAFillModeForwards 动画开始之后layer的状态将保持在动画的最后一帧,而removedOnCompletion的默认属性值为YES,所以为了使动画结束之后layer保持结束状态,应将removedOnCompletion设置为NO
- kCAFillModeBackwards 将会立即执行动画的第一帧,无论是否设置beginTime属性
- kCAFillModeBoth kCAFillModeForwards和kCAFillModeBackwards的组合状态
- kCAFillModeRemoved 动画将在设置的beginTime开始执行(若有设置beginTime属性,则动画立刻执行),而动画执行完成后将会将layer的状态恢复原状
- timingFunction 设置动画的时间变化
- fromValue 所要改变属性的起始值
- toValue 所要改变属性的结束时的值
- byValue 所要改变属性相同起始值的改变量
- 注:若将removedOnCompletion设置为false状态,则可能会引起循环引用的问题
- 原因:由于CAAnimation的delegate使用的Strong类型(强引用类型)
一般创建动画的时候,会使用到KeyPath的属性
备注:KeyPath的值
- positon - 移动位置(CGPoint)
- opacitu - 透明度(0-1)
- bounds - 变大与位置(CGRect)
- bounds.size - 由小变大(CGSize)
- backgroundColor - 背景颜色(CGColor)
- cornerRadius - 渐变圆角(任意数值)
- borderWidth - 改变边框border的大小(图形周围边框,border默认为黑色) (任意数值)
- contens - 改变layer内容(图片) 若想要达到改变内容的动画效果,则要先在运行之前定义好layer的contents (CGImage)
- transform.scale - 缩放,放大(0.0-1.0)
- transform.rotation.x - 旋转动画(翻转,沿着X轴)(M_PI * n)
- transform.rotation.y - 旋转动画(沿着Y轴)(M_PI * n)
- transform.rotation.z - 旋转动画(沿着Z轴)(M_PI * n)
- transform.transiation.x - 横向移动(沿着X轴)(任意数值)
- transform.transiation.y - 纵向移动(沿着Y轴)(任意数值)
旋转动画
#pragma mark - 旋转动画 -
-(void)setRotateView
{
//1.创建一个View图层
UIView *animationView = [[UIView alloc]initWithFrame:CGRectMake(10, 50, 70, 70)];
animationView.backgroundColor = [UIColor orangeColor];
//将AnimationView添加到self.view上
[self.view addSubview:animationView];
//2.创建动画图层
/**
3.设置keyPath的常用属性:
transform.rotation.x 围绕x轴旋转
transform.rotation.y 围绕y轴旋转
transform.rotation.z 围绕z轴旋转
*/
CABasicAnimation * basic = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"];
//4.设置beginTime指定动画开始的时间,从开始延迟几秒的话,设置为CACurrentMediaTime() + 秒数的方式
basic.beginTime = 0.0;
//5.设置toValue所要改变属性的结束时的值
basic.toValue = [NSValue valueWithCGPoint:CGPointMake(2*M_PI, 0)];
//6.设置duration动画的持续时间
basic.duration = 1.5;
//7.设置repeatCount动画的持续次数
basic.repeatCount = INFINITY;
/**
timingFunction 设置动画的时间变化
kCAMediaTimingFunctionLinear 在整个动画时间内动画都是以相同速度来改变 - 匀速运动
kCAMediaTimingFunctionEaseIn 动画开始慢,之后加速 - 加速运动
kCAMediaTimingFunctionEaseOut 动画开始快,之后减速 - 减速运动
kCAMediaTimingFunctionEaseInEaseOut 动画在开始和结束都慢,中间时间段内速度较快
kCAMediaTimingFunctionDefault 默认动画
*/
//[basic setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
//8.将动画添加到图层
[animationView.layer addAnimation:basic forKey:@"basic"];
}
移动动画
#pragma mark - 移动动画 -
-(void)SetMoveAnimationView
{
//1.创建一个View图层
UIView *animationView = [[UIView alloc]initWithFrame:CGRectMake(10, 120, 70, 70)];
animationView.backgroundColor = [UIColor orangeColor];
//将AnimationView添加到self.view上
[self.view addSubview:animationView];
//2.创建动画图层
/**3.position 设置内容(eg:UIImage)*/
CABasicAnimation * basic = [CABasicAnimation animationWithKeyPath:@"position"];
//4.fromValue所要改变属性的起始值
basic.fromValue = [NSValue valueWithCGPoint:CGPointMake(40, 240)];
//5.设置toValue所要改变属性的结束时的值
basic.toValue = [NSValue valueWithCGPoint:CGPointMake(300, 240)];
//6.设置duration动画的持续时间
basic.duration = 2;
//7.设置repeatCount动画的持续次数
basic.repeatCount = INFINITY;
//8.autoreverses动画结束时是否执行逆动画
basic.autoreverses = YES;
//10.将动画添加到图层
[animationView.layer addAnimation:basic forKey:@"basic"];
}
背景颜色变化动画
#pragma mark - 背景颜色变化动画 -
-(void)SetBackgroundColorChangeAnimationView
{
//1.创建一个View图层
UIView *animationView = [[UIView alloc]initWithFrame:CGRectMake(100, 50, 70, 70)];
animationView.backgroundColor = [UIColor orangeColor];
//将AnimationView添加到self.view上
[self.view addSubview:animationView];
//2.创建动画图层
//backgroundColor 设置背景颜色的变化
CABasicAnimation * basic = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
//4.fromValue所要改变属性的起始值
basic.fromValue = (__bridge id _Nullable)([UIColor orangeColor].CGColor);
//5.设置toValue所要改变属性的结束时的值
basic.toValue = (__bridge id _Nullable)([UIColor lightGrayColor].CGColor);
//6.设置duration动画的持续时间
basic.duration = 2;
//7.设置repeatCount动画的持续次数
basic.repeatCount = INFINITY;
//8.autoreverses动画结束时是否执行逆动画
basic.autoreverses = YES;
//10.将动画添加到图层
[animationView.layer addAnimation:basic forKey:@"basic"];
}
内容改变动画
#pragma mark - 内容改变动画 -
-(void)SetContantChangeAnimationView
{
//1.创建一个View图层
UIImageView *animationView = [[UIImageView alloc]initWithFrame:CGRectMake(200, 50, 70, 70)];
animationView.image = [UIImage imageNamed:@"from"];
[self.view addSubview:animationView];
//2.创建动画图层 contents
CABasicAnimation * basic = [CABasicAnimation animationWithKeyPath:@"contents"];
//5.设置toValue所要改变属性的结束时的值
basic.toValue = (__bridge id _Nullable)([UIImage imageNamed:@"to"].CGImage);
//6.设置duration动画的持续时间
basic.duration = 1.5;
//7.设置repeatCount动画的持续次数
basic.repeatCount = INFINITY;
//8.autoreverses动画结束时是否执行逆动画
basic.autoreverses = YES;
//10.将动画添加到图层
[animationView.layer addAnimation:basic forKey:@"basic"];
}
转换圆角动画
#pragma mark - 圆角变化动画 -
-(void)SetRadiusView
{
//1.创建一个View图层
UIView *animationView = [[UIView alloc]initWithFrame:CGRectMake(10, 310, 70, 70)];
animationView.backgroundColor = [UIColor purpleColor];
[self.view addSubview:animationView];
animationView.layer.masksToBounds = YES;
//2.创建动画图层 contents
CABasicAnimation * basic = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
//5.设置toValue所要改变属性的结束时的值
basic.toValue = [NSValue valueWithCGPoint:CGPointMake(35, 0)];
//6.设置duration动画的持续时间
basic.duration = 2;
//7.设置repeatCount动画的持续次数
basic.repeatCount = INFINITY;
//8.autoreverses动画结束时是否执行逆动画
basic.autoreverses = YES;
//10.将动画添加到图层
[animationView.layer addAnimation:basic forKey:@"basic"];
}
按比例缩放动画
#pragma mark - 按比例缩放动画 -
-(void)SetZoomAnimationView
{
//1.创建一个View图层
UIView *animationView = [[UIView alloc]initWithFrame:CGRectMake(10, 400, 70, 70)];
animationView.backgroundColor = [UIColor purpleColor];
[self.view addSubview:animationView];
//2.创建动画图层 contents
/**
transform.scale 按比例缩放 - 0.8
transform.scale.x 缩放宽的比例
transform.scale.y 缩放高的比例
*/
CABasicAnimation * basic = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
basic.fromValue = [NSValue valueWithCGPoint:CGPointMake(0.3, 0)];
//5.设置toValue所要改变属性的结束时的值
basic.toValue = [NSValue valueWithCGPoint:CGPointMake(1.3, 0)];
//6.设置duration动画的持续时间
basic.duration = 2;
//7.设置repeatCount动画的持续次数
basic.repeatCount = INFINITY;
//8.autoreverses动画结束时是否执行逆动画
basic.autoreverses = YES;
//10.将动画添加到图层
[animationView.layer addAnimation:basic forKey:@"basic"];
}
按指定大小进行缩放动画
#pragma mark - 指定大小缩放 -
-(void)SetAssginZoomView
{
//1.创建一个View图层
UIView *animationView = [[UIView alloc]initWithFrame:CGRectMake(120, 400, 70, 70)];
animationView.backgroundColor = [UIColor purpleColor];
[self.view addSubview:animationView];
//2.创建动画图层 contents
CABasicAnimation * basic = [CABasicAnimation animationWithKeyPath:@"bounds"];
//5.设置toValue所要改变属性的结束时的值
basic.toValue = [NSValue valueWithCGRect:CGRectMake(800, 500, 90, 30)];
//6.设置duration动画的持续时间
basic.duration = 2;
//7.设置repeatCount动画的持续次数
basic.repeatCount = INFINITY;
//8.autoreverses动画结束时是否执行逆动画
basic.autoreverses = YES;
//10.将动画添加到图层
[animationView.layer addAnimation:basic forKey:@"basic"];
}
设置渐变动画(透明)
#pragma mark - 透明动画 -
-(void)SetAlphaAnimationView
{
//1.创建一个View图层
UIView *animationView = [[UIView alloc]initWithFrame:CGRectMake(300, 50, 70, 70)];
animationView.backgroundColor = [UIColor purpleColor];
[self.view addSubview:animationView];
//2.创建动画图层 contents
CABasicAnimation * basic = [CABasicAnimation animationWithKeyPath:@"opacity"];
basic.fromValue= [NSValue valueWithCGPoint:CGPointMake(0.3, 0)];
//5.设置toValue所要改变属性的结束时的值
basic.toValue = [NSValue valueWithCGPoint:CGPointMake(1, 0)];
//6.设置duration动画的持续时间
basic.duration = 0.6;
//7.设置repeatCount动画的持续次数
basic.repeatCount = INFINITY;
//8.autoreverses动画结束时是否执行逆动画
basic.autoreverses = YES;
//10.将动画添加到图层
[animationView.layer addAnimation:basic forKey:@"basic"];
}
- CAKeyframeAnimation(关键帧动画)
常用属性有:
- values 当path=nil的时候才起作用
- keyTimes 一个包含若干NSNumber(浮点型值在0.0~1.0之间)对象值得数组,用来区分动画的分割时机
- calculationMode 计算模式 主要针对的是每一帧的内容来为一个坐标点的情况,也就是对anchorPoint和Position进行的动画
- kCAAnimationLinear 默认值 自定义控制动画的时间,可以设置keyTimes,表示当关键帧为坐标点的时候,关键帧之间之间直线相连进行插针计算 线性的
- kCAAnimationDiscrete 离散的 不进行插值计算 所有关键帧之间逐个儿进行显示
- kCAAnimationPaced 节奏动画,自动计算动画的运动时间,使得动画匀速运行 keyTimes和timingFunctions无效
- kCAAnimationCubic 对关键帧为坐标点的关键帧进行圆滑曲线相连后进行插值计算 若为曲线形状,可通过tensionValues,continuityValues,biasValues来进行调整自定义,其主要目的是使得运行轨迹变得圆滑,而曲线动画则要设置timingFunctions
- kCAAnimationCubicPaced 在系统时间内运行的距离相同,keyTimes和timingFunctions无效
- rotationMode 旋转样式
- kCAAnimationRotateAuto 根据路径自动旋转
- kCAAnimationRotateAutoReverse 根据路径自动翻转
创建一个例子来实现一下
#pragma mark - CAKeyframeAnimation 核心动画里面的帧动画 -
-(void)setCAKeyframeAnimationView
{
//1.创建View
UIView * keyFrameAnimation = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 200, 300)];
keyFrameAnimation.center = CGPointMake(self.view.frame.size.width/2.0, self.view.frame.size.height/2.0-50);
//2.创建贝塞尔曲线
UIBezierPath * bezierPath = [UIBezierPath bezierPathWithOvalInRect:keyFrameAnimation.frame];
//3.再创建一个存放动画的View
UIView * animationView = [[UIView alloc]initWithFrame:CGRectMake(50, 50, 70, 80)];
animationView.backgroundColor = [UIColor orangeColor];
[self.view addSubview:animationView];
//2.创建帧动画
CAKeyframeAnimation * keyframe = [CAKeyframeAnimation animationWithKeyPath:@"position"];
keyframe.duration = 5;
keyframe.path = bezierPath.CGPath;
/**
calculationMode的属性:
kCAAnimationLinear 默认值 自定义控制动画的时间,可以设置keyTimes,表示当关键帧为坐标点的时候,关键帧之间之间直线相连进行插针计算 线性的
kCAAnimationDiscrete 离散的 不进行插值计算 所有关键帧之间逐个儿进行显示
kCAAnimationPaced 节奏动画,自动计算动画的运动时间,使得动画匀速运行 keyTimes和timingFunctions无效
kCAAnimationCubic 对关键帧为坐标点的关键帧进行圆滑曲线相连后进行插值计算 若为曲线形状,可通过tensionValues,continuityValues,biasValues来进行调整自定义,其主要目的是使得运行轨迹变得圆滑,而曲线动画则要设置timingFunctions
kCAAnimationCubicPaced 在系统时间内运行的距离相同,keyTimes和timingFunctions无效
*/
//calculationMode 计算模式 主要针对的是每一帧的内容来为一个坐标点的情况,也就是对anchorPoint和Position进行的动画
keyframe.calculationMode = kCAAnimationPaced;
keyframe.repeatCount = INFINITY;
//设置旋转样式
/**
kCAAnimationRotateAuto 根据路径自动旋转
kCAAnimationRotateAutoReverse 根据路径自动翻转
*/
keyframe.rotationMode = kCAAnimationRotateAutoReverse;
[animationView.layer addAnimation:keyframe forKey:@"keyframe"];
//创建CAShapeLayer
CAShapeLayer * shape = [[CAShapeLayer alloc]init];
shape.strokeColor = [UIColor lightGrayColor].CGColor;
shape.fillColor = [UIColor clearColor].CGColor;
shape.lineWidth = 0.5;
shape.lineJoin = kCALineJoinRound;
shape.lineCap = kCALineCapRound;
shape.path = bezierPath.CGPath;
[self.view.layer addSublayer:shape];
}
- CATransition(转场动画)
CATransition的常用属性有:
- type - 转场动画的类型
- kCATransitionFade 淡出效果 (支持方向)
- kCATransitionMoveIn 将新视图移动到旧视图上 (支持方向)
- kCATransitionPush 用新视图来推出旧视图 (支持方向)
- kCATransitionReveal 将旧视图移开后再显示新视图 (支持方向)
- subtype - 转场动画将要去往的方向
- kCATransitionFromRight 从右侧转场
- kCATransitionFromLeft 从左侧转场
- kCATransitionFromTop 从顶部转场
- kCATransitionFromBottom 从底部转场
- TimingFunction - 时间函数
- repeatCount - 重复显示次数
创建一个例子来实现上述属性:
#pragma mark - CATransition 主要用于转场动画从一个场景以动画的形式来过渡到另一个场景 -
-(void)setCATransitionView
{
//1、创建显示效果名称的label
self.textLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 200, 300)];
self.textLabel.center = CGPointMake(self.view.frame.size.width/2.0, self.view.frame.size.width/2.0);
self.textLabel.backgroundColor = [UIColor colorWithRed:88/255.0 green:161/255.0 blue:86/255.0 alpha:1];
self.textLabel.textColor = [UIColor whiteColor];
self.textLabel.font = [UIFont systemFontOfSize:16];
self.textLabel.numberOfLines = 0;
self.textLabel.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:self.textLabel];
//创建按钮
self.clickButton = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 180, 40)];
self.clickButton.center = CGPointMake(self.view.frame.size.width/2.0f, self.view.frame.size.height-240);
self.clickButton.backgroundColor = [UIColor blackColor];
[self.clickButton setTitle:@"AnimationChange" forState:UIControlStateNormal];
self.clickButton.titleLabel.textAlignment = NSTextAlignmentCenter;
[self.clickButton addTarget:self action:@selector(ClickButton) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.clickButton];
}
//MARK:点击按钮,开始改变转场动画效果
-(void)ClickButton
{
//创建转场动画图层
CATransition * transition = [CATransition new];
//设置代理事件
transition.delegate = self;
//设置时间
transition.duration = 1.0;
//设置时间函数
/**
kCAMediaTimingFunctionLinear
kCAMediaTimingFunctionEaseIn
kCAMediaTimingFunctionEaseOut
kCAMediaTimingFunctionEaseInEaseOut
kCAMediaTimingFunctionDefault 默认
*/
[transition setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
//设置转场动画类型 默认从第一个开始
[transition setType:self.animationArray[_index]];
//设置转场动画的方向
/**
kCATransitionFromRight 从右侧转场
kCATransitionFromLeft 从左侧转场
kCATransitionFromTop 从顶部转场
kCATransitionFromBottom 从底部转场
*/
transition.subtype = kCATransitionFromLeft;
//设置重复次数
transition.repeatCount = 1;
//设置键值对
[transition setValue:@"transitionAnim" forKey:@"anim"];
//添加到视图
[self.textLabel.layer addAnimation:transition forKey:@"transition"];
self.textLabel.text = [NSString stringWithFormat:@"This Animation was %@",self.animationArray[_index]];
}
#pragma mark - 实现CAAnimationDelegate方法 -
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
_index = (_index
- CASpringAnimation(弹簧动画)
CASpringAnimation的常用属性有:
- mass 质量,影响图层运动时的弹簧惯性,质量越大,弹簧的拉伸和压缩的幅度越大,动画的速度变慢,并且波动幅度变大
- stiffness 刚度系数 = 劲度系数/弹性系数 当刚度系数越大的时候,形变所产生的力就越大,运动就越快
- damping 阻尼系数 阻止弹簧伸缩的系数,阻尼系数越大,停止越快
- initialVelocity 初始速率,动画的初始速度大小速率为正数时,速度方向与运动方向一致,当速率为负数的时候,速度方向和运动方向相反
- settingDuration 结算时间,返回弹簧动画到停止时的估算时间,根据当前的动画参数估算通常动画的时间使用结算时间比较准确
创建一个例子来实现上述属性
#pragma mark - CASpringAnimation 弹簧动画-
-(void)setCASpringAnimationView
{
//创建label
self.textLabel = [[UILabel alloc]initWithFrame:CGRectMake(10, 200, 50, 30)];
self.textLabel.backgroundColor = [UIColor redColor];
[self.view addSubview:self.textLabel];
//创建弹簧动画
CASpringAnimation * spring = [CASpringAnimation animationWithKeyPath:@"position.x"];
spring.damping = 5;
spring.stiffness = 100;
spring.mass = 1;
spring.initialVelocity = 0;
spring.fromValue = [NSValue valueWithCGPoint:CGPointMake(self.textLabel.layer.position.x, 0)];
spring.toValue = [NSValue valueWithCGPoint:CGPointMake(self.textLabel.layer.position.x+100, 0)];
spring.autoreverses = YES;
spring.repeatCount = INFINITY;
[self.textLabel.layer addAnimation:spring forKey:spring.keyPath];
}
备注:
- CABasicAnimation(基础动画)和CAKeyframeAnimation(帧动画)的区别&联系
- CABasicAnimation可以看做是最多只有两个关键帧的CAKeyframeAnimation