CAAnimation(动画详解,持续更新)

导读:

      笔者最近要做一个直播类的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)]这四个点决定的三次贝塞尔曲线,头尾为起点和终点,中间的两个点是控制点.


kCAMediaTimingFunctionDefault

上图中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"];

图1(CABasicAnimation简单运用)

四、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"];


图2(CAKeyframeAnimation用法)

五、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"];


图3(CASpringAnimation简单运用)

六、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"];


图3(1.CAAnimationGroup运用)
图4(2.CAAnimationGroup运用)

推荐阅读更多精彩内容

  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 5,092评论 4 23
  • 先看看CAAnimation动画的继承结构 CAAnimation{ CAPropertyAnimation { ...
    时间不会倒着走阅读 735评论 0 1
  • 在iOS实际开发中常用的动画无非是以下四种:UIView动画,核心动画,帧动画,自定义转场动画。 1.UIView...
    请叫我周小帅阅读 1,861评论 1 22
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 3,352评论 4 10
  • 一、UIKit动画 第一种写法是利用属性,结合beginAnimations、commitAnimations 第...
    Gary_Tseng阅读 346评论 1 2