导读:
笔者最近要做一个直播类的APP,为了对这个APP的准备特此重温下各种动画效果,并且网络上大多写此类的作者,笔者认为他们并没有做出比较完善的划分以及各种属性的分类。由此笔者带着各位来看看这个强大的CAAnimation类以及他的子类CAPropertyAnimation、CATransition、CAAnimationGroup。并且以及其子类CAPropertyAnimation的子类CABasicAnimation以及CAKeyframeAnimation这两个我们做动画的时候经常遇到的类。(希望读者能看完有所提升,并且希望有人能指正文中不正确的地方,让笔者能及时更改以免造成其他读者理解错误。)
类的介绍
一、CAAnimation(集成于NSObject类,可以这么说吧它是所有动画类的“根类”了,此类用的不多,我们都用它的子类)
1、属性介绍
①CAMediaTimingFunction *timingFunction;(时间函数定义动画的节奏。默认为nil其表示的是线性踱来踱去;而CAMediaTimingFunction类官方给出的解释是其代表的是一个描述时间曲线的函数。其函数映射一个范围为[0,1]的输入时间,并且其输出时间也在[0,1]。可以这样说它表示的是在一个关键帧的持续时间,它有五种预定义的时间函数名字的常量变量:kCAMediaTimingFunctionLinear, kCAMediaTimingFunctionEaseIn, kCAMediaTimingFunctionEaseOut, kCAMediaTimingFunctionEaseInEaseOut, kCAMediaTimingFunctionDefault.下面借用别人的绘图描述)下图展示了前面四种Timing Function的曲线图,横座标表示时间,纵座标表示变化量,这点需要搞清楚(并不是平面座标系中xy).
上面的kCAMediaTimingFunctionDefault对应的函数曲线其实就是通过[(0.0,0.0), (0.25,0.1), (0.25,0.1), (1.0,1.0)]这四个点决定的三次贝塞尔曲线,头尾为起点和终点,中间的两个点是控制点.
上图中P0是起点,P3是终点,P1和P2是两个控制点
如果时间变化曲线既不是直线也不是贝塞尔曲线,而是自定义的,又或者某个图层运动的轨迹不是直线而是一个曲线,这些是基本动画无法做到的,所以会有CAKeyframeAnimation,也即所谓的关键帧动画(后面介绍).
②BOOL removedOnCompletion;(默认为YES,表示此动画是否在动画完成的时候移除)
2、代理方法介绍
①- (void)animationDidStart:(CAAnimation *)anim;(动画开始)
②- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;(动画结束方法,flag表示是否动画结束后是否被删除)
二、CAPropertyAnimation(继承于CAAnimation类,里面说这是一个基于属性的动画类。一般不使用它而是使用它的子类)
1、属性介绍
①NSString *keyPath;(该属性值返回创建CAPropertyAnimation时指定的参数。)
②BOOL additive;(该属性指定该属性动画是否以当前动画效果为基础。)
③BOOL cumulative;(该属性指定动画是否为累加效果。)
④CAValueFunction *valueFunction;(该属性值是一个CAValueFunction对象,该对象负责对属性改变的插值计算,系统已经提供了默认的插值计算方式,因此一般无须指定该属 性。)
2、方法介绍
①+ (instancetype)animationWithKeyPath:(nullable NSString *)path;(表示创建动画以及动画的效果,path表示动画的效果,后面会介绍常用的动画标识)
三、CABasicAnimation(继承于CAPropertyAnimation类。基本属性动画,我们暂且把它看为只有头尾关键帧的动画类)
1、属性介绍
①id fromValue;(表示开始值)
②id toValue;(表示结束值)
③id byValue;(该属性指定动画是否为累加效果。)
2、用法简介(后面会有比较完整的介绍在此先让读者作为了解,在此分为图片和手打,以便观看与复制)
//创建动画,且参数为所做动画的标识(比较重要,后面会介绍都大致有哪些标识)
CABasicAnimation *basicAnimatin=[CABasicAnimation animationWithKeyPath:@"position"];
//设置开始值
[basicAnimatin setFromValue:[NSValue valueWithCGPoint:layer.frame.origin]];
//设置结束值
[basicAnimatin setToValue:[NSValue valueWithCGPoint:CGPointMake(100, 11)]];
//设置动画完成后是否动画返回开始值得位置(此属性默认为NO。)
basicAnimatin.autoreverses= YES;
//设置动画为累加效果(此属性默认为NO。)
basicAnimatin.cumulative= YES;
//设置动画完成后不返回为原位置。(此属性默认为YES。)
basicAnimatin.removedOnCompletion=NO;
//此属性为动画填充模式表示动画完成后的状态是怎样的(有4个值kCAFillModeForwards表示对象状态为动画结束时的状态;kCAFillModeBackwards表示开始的状态;kCAFillModeBoth表示开始和结束的状态(不知道这个是干嘛);kCAFillModeRemoved表示动画移除(我感觉和kCAFillModeBackwards这个有点大致相同,且此为默认值))。
basicAnimatin.fillMode=kCAFillModeForwards;
//设置动画完成的时间
[basicAnimatin setDuration:5.0];
//layer.position=CGPointMake(100, 11);(此属性我认为是layer的中心点)
//给layer添加动画第二个参数是该动画的一个标志(自己随意设置例如“aaaa”)
[layer addAnimation:basicAnimatin forKey:@"aaaa"];
四、CAKeyframeAnimation(继承于CAPropertyAnimation类。是关键帧动画,我们可以指定其动画执行过程中每个阶段的动画,也就是说我们运用此类,我们可以做任何我们想要的动画效果)
1、属性介绍
①NSArray *values;(表示动画执行的各个值(各个动作))
②CGPathRef path;(表示动画的路径的行为动画函数,当为非nil的时候覆盖其“值”的属性,它默认为nil。它会表示以恒定的速度沿着路径进行动画,所以一般我们与calculationMode这个属性搭配使用,后面介绍calculationMode这个属性)
③NSArray*keyTimes;(该属性可以定义动画执行过程中每个值代表的节奏可以说是速度吧,且与values这个属性中定义的相对应。而它每个值是浮点数且区间为[0,1])
④NSArray*timingFunctions;(该属性表示CAMediaTimingFunction(CAAnimation类中有此属性)的数组,如果你在此数组定义了n个关键帧,则就有n-1个CAMediaTimingFunction对象,它所描述的是关键帧到帧的节奏(速度))
⑤NSString *calculationMode;(②中我们说要介绍此属性,此属性代表的是计算模式分别有kCAAnimationLinear(线性)kCAAnimationDiscrete(离散即不连续的)kCAAnimationPaced(节奏)kCAAnimationCubic(立方)kCAAnimationCubicPaced(立方节奏)当它被我们设置为kCAAnimationPaced(节奏)或kCAAnimationCubicPaced(节奏立方)的时候我们所设置的③ keyTimes和④ timingFunctions这两个属性会被忽略。此属性默认为线性。如果读者不明白我借用网上一人所写的描述)
kCAAnimationLinear calculationMode的默认值,表示当关键帧为座标点的时候,关键帧之间直接直线相连进行插值计算;
kCAAnimationDiscrete 离散的,就是不进行插值计算,所有关键帧直接逐个进行显示; kCAAnimationPaced 使得动画均匀进行,而不是按keyTimes设置的或者按关键帧平分时间,此时keyTimes和timingFunctions无效;
kCAAnimationCubic 对关键帧为座标点的关键帧进行圆滑曲线相连后插值计算,对于曲线的形状还可以通过tensionValues⑥,continuityValues⑦,biasValues⑧来进行调整自定义,这里的数学原理是Kochanek–Bartels spline,这里的主要目的是使得运行的轨迹变得圆滑;
kCAAnimationCubicPaced 看这个名字就知道和kCAAnimationCubic有一定联系,其实就是在kCAAnimationCubic的基础上使得动画运行变得均匀,就是系统时间内运动的距离相同,此时keyTimes以及timingFunctions也是无效的.
⑥NSArray*tensionValues;(动画的张力,当动画为立方计算模式的时候此属性提供了控制插值,因为每个关键帧都可能有张力所以连续性会有所偏差它的范围为[-1,1]。⑦⑧同样是此作用)
⑦NSArray*continuityValues;(动画的连续性值)
⑧NSArray*biasValues;(动画的偏斜率)
⑨NSString *rotationMode;(定义了动画是否沿着路径旋转。它有两个值kCAAnimationRotateAuto(自动旋转)kCAAnimationRotateAutoReverse(自动倒转)其默认值为nil,且当没有设置路径的时候我们用此属性的话也是可行的)
2、用法简介(后面会有比较完整的介绍在此先让读者作为了解)
CAKeyframeAnimation *keyAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"];
//设置每个阶段的位置(第一个代表的是起始位置,最后一个代表的是结束位置)注意这CGPoint代表的是中点。
keyAnimation.values=@[[NSValue valueWithCGPoint:CGPointMake(0, 0)],[NSValue valueWithCGPoint:CGPointMake(200, 100)],[NSValue valueWithCGPoint:CGPointMake(200, 200)],[NSValue valueWithCGPoint:CGPointMake(100, 200)],[NSValue valueWithCGPoint:CGPointMake(100, 100)]];
keyAnimation.autoreverses= YES;
keyAnimation.removedOnCompletion=NO;
keyAnimation.cumulative= YES;
keyAnimation.fillMode=kCAFillModeForwards;
keyAnimation.duration=4.0f;
//设置其速度变化的函数
keyAnimation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
//设置的是每个阶段速度变化的函数
//keyAnimation.timingFunctions=@[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn],[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn],[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
//动画重复的次数
keyAnimation.repeatCount=MAXFLOAT;
[layer addAnimation:keyAnimation forKey:@"asdasd"];
五、CASpringAnimation(继承于CABasicAnimation类。是弹框动画)
1、属性介绍
①CGFloat mass;(质量,影响图层运动时的弹簧惯性,质量越大,弹簧拉伸和压缩的幅度越大。默认为1,且设置的时候必须大于0)
②CGFloat stiffness;(刚度系数(劲度系数/弹性系数),刚度系数越大,形变产生的力就越大,运动越快。默认为100,且设置的时候必须大于0)
③CGFloat damping;(阻尼系数,阻止弹簧伸缩的系数,阻尼系数越大,停止越快,默认为10,且设置的时候必须大于0)
④CGFloat initialVelocity;(初始速率,动画视图的初始速度大小速率为正数时,速度方向与运动方向一致,速率为负数时,速度方向与运动方向相反。默认为0)
⑤CFTimeInterval settlingDuration;(结算时间,返回弹簧动画到停止时的估算时间,根据当前的动画参数估算,通常弹簧动画的时间使用结算时间比较准确)
2、用法简介
CASpringAnimation *springAnimation=[CASpringAnimation animationWithKeyPath:@"position"];
//设置阻尼系数(此值越大弹框效果越不明显)
springAnimation.damping=1;
//设置刚度系数(此值越大弹框效果越明显)
springAnimation.stiffness=10;
//设置质量大小(越大惯性越大)
springAnimation.mass=2;
//设置初始速度
springAnimation.initialVelocity=10;
[springAnimation setFromValue:[NSValue valueWithCGPoint:layer.frame.origin]];
//设置结束值
[springAnimation setToValue:[NSValue valueWithCGPoint:CGPointMake(self.view.center.x-50, self.view.center.y-200)]];
springAnimation.autoreverses= YES;
//设置动画为累加效果(此属性默认为NO。)
springAnimation.cumulative= YES;
//设置动画完成后不返回为原位置。(此属性默认为YES。)
springAnimation.removedOnCompletion=NO;
// springAnimation.repeatCount=MAXFLOAT;(读者自行测试添加此属性的时候会有如何效果)
[springAnimation setDuration:5.0];
[layer addAnimation:springAnimation forKey:@"sadasd"];
六、CATransition(继承于CAAnimation类。此类提供了动画的渐变效果)
1、属性介绍
①NSString *type;(表示其渐变的效果的类型。有4种分别为kCATransitionFade(消退)kCATransitionMoveIn(渐入)kCATransitionPush(推动)kCATransitionReveal(揭开)等不同的效果)
②NSString *subtype;(此类用于过渡运动方向的转变且分为上下左右四种:kCATransitionFromRight、kCATransitionFromLeft、kCATransitionFromTop、kCATransitionFromBottom)
③float startProgress;(表示渐变开始的数值且其大小区间为[0,1],注意它必须小于或等于④)
④float endProgress;(同③)
⑤id filter;(默认值为nil,官方给出的解释为实现过渡的对象,当我们没有设置type和subtype的时候,我们就必须实现inputImage、inputTargetImage和inputTime的值以及outputImage的输出值(其实我也不是很明白这个属性的运用,如果有人知道请在评论下方打出,能让我学习一下。))
2、用法简介
在此是在一个buttonClick方法内部写的
[_button setImage:[UIImage imageNamed:@"asd"] forState:UIControlStateNormal];
CATransition *transition=[CATransition animation];
//设置渐变效果
[transition setType:kCATransitionReveal];
//设置动画方向
[transition setSubtype:kCATransitionFromBottom];
// transition.startProgress=0.5;
// transition.endProgress=1;
transition.duration=3;
[_button.imageView.layer addAnimation:transition forKey:@"adas"];
七、CAAnimationGroup(继承于CAAnimation类。此类顾名思义是一个动画的组合可以添加多种动画)
1、属性介绍
①NSArray*animations;(用于添加需要完成的动画)
2、用法简介
//第一步,我准备让其按照一个我所画出的路程进行动画。
UIBezierPath *path=[UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(25, 25)];//设置路线的起始点(是以中心点为坐标的(不知道咋解释了))
[path addQuadCurveToPoint:CGPointMake(self.view.frame.size.width-50, self.view.frame.size.height-50) controlPoint:CGPointMake(200, 100)];//画二次贝塞尔曲线,第一个参数是终点,第二个是控制点你可以把它当为这个曲线的最高点/最低点(顶点)。
/*path.lineWidth=5.0; path.lineCapStyle=kCGLineCapRound; path.lineJoinStyle=kCGLineJoinRound; UIColor *lineColor=[UIColor redColor]; [lineColor set]; [path stroke];*///当你添加这些东西的时候你会发现根本绘不出路线,并且会出现: CGContextRestoreGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.这个错误。要解决的话你需要在一个view的- (void)drawRect:(CGRect)rect方法内部画出显示。
CAKeyframeAnimation *keyAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"];
keyAnimation.path=path.CGPath;//把路线给它
//第二步,我们做一个缩放的动画
CABasicAnimation *basicAnimation=[CABasicAnimation animationWithKeyPath:@"transform"];
basicAnimation.fromValue=[NSValue valueWithCATransform3D:CATransform3DIdentity];
//让他做的距离是self.view.frame.size.height-50
[basicAnimation setToValue:[NSValue valueWithCATransform3D:CATransform3DMakeScale(2, 1, 100)]];//第一个参数是你可以把它看为宽度的倍数,第二个是高度的倍数。第三个是空间z轴这里我们不予考虑
basicAnimation.removedOnCompletion = YES;
CAAnimationGroup *animationGroup=[CAAnimationGroup animation];
// 设置动画完成后是否动画返回开始值得位置(此属性默认为NO。)
animationGroup.autoreverses= NO;
//设置动画完成后不返回为原位置。(此属性默认为YES。)
animationGroup.removedOnCompletion=NO;
animationGroup.fillMode=kCAFillModeForwards;
animationGroup.duration=6.f;
animationGroup.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];//可以把它看为动画执行的速度函数,详情请参考CAAnimation类的属性介绍
animationGroup.animations=@[basicAnimation,keyAnimation];
[label.layer addAnimation:animationGroup forKey:@"gfds"];