iOS 动画基础一:CAAnimation和CAPropertyAnimation

一、前言

之前做的动画都比较简单,用UIView的自带动画就能实现,最近接到一些稍微复杂的动画,于是回顾了Core Animation的一些知识,本章主要回顾下Core Animation的一些基础知识

二、Core Animation的类图和常用字段及方法

iOS 动画基础一:CAAnimation和CAPropertyAnimation_第1张图片
image.png

A、先看下基类:CAAnimation

First:在详细讲解基类之前先来看下CAAnimation所遵循的协议 CAMediaTiming 这里不做讲解,只需要知道:
1、CALayer和CAAnimation都遵循了该协议。
2、该协议的属性都有一个默认值【这对理解CAAnimation的+defaultValueForKey:方法很有用】

Second: 再来看下动画自定义时间函数CAMediaTimingFunction

//线性动画
kCAMediaTimingFunctionLinear
 //淡入
kCAMediaTimingFunctionEaseIn
//淡出
kCAMediaTimingFunctionEaseOut
//淡入淡出
kCAMediaTimingFunctionEaseInEaseOut
//默认
kCAMediaTimingFunctionDefault

Third:看一下CAAnimationDelegate代理

/* Called when the animation begins its active duration. */
/* 监测动画开始的时间点 */
- (void)animationDidStart:(CAAnimation *)anim;

/* Called when the animation either completes its active duration or
 * is removed from the object it is attached to (i.e. the layer). 'flag'
 * is true if the animation reached the end of its active duration
 * without being removed. */
/* 监测动画停止的时间点 1、flag==true 说明动画完成  2、flag==false 说明动画被移除 */
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;

CAAnimation

@interface CAAnimation : NSObject
    
{
@private
  void *_attr;
  uint32_t _flags;
}

/* Creates a new animation object. */
/* 通过类方法创建一个CAAnimation对象 
CAAnimation是一个动画抽象类,但是不要直接使用CAAnimation类,而是使用它的子类,
如上图所示展示的就是它的家族成员子类们,CAAnimation遵守CAMediaTiming和CAAction协议,它是直接作用在CALayer上的,并非UIView上,
动画执行过程不在主线程上进行,所以不会阻塞主线程。先来看看CAnimation都定义了哪些属性,方法。
*/
+ (instancetype)animation;

/* Animations implement the same property model as defined by CALayer.
 * See CALayer.h for more details. */
/*注意这里是类方法:
 这里相当于对一些属性的默认值进行了拦截,可以在自定义的子类中重写该方法,重新设置默认值,
比如 我自定义一个动画类 
@interface LYCACustomAnimation : CABasicAnimation 
这里 动画时间属性 duration 的默认值是0,我想把自定义类的这个属性默认值更改为1.0,可以这么实现

+ (id)defaultValueForKey:(NSString *)key {
    if ([key isEqualToString:@"duration"]) {
        return [NSNumber numberWithDouble:1.0];
    }
    return [super defaultValueForKey:key];
}
*/
+ (nullable id)defaultValueForKey:(NSString *)key;
/*注意这里是对象方法
 判断一个key是否能被归档, 可以理解为当前类对象是否包含“key”属性*/
- (BOOL)shouldArchiveValueForKey:(NSString *)key;

/* A timing function defining the pacing of the animation. Defaults to
 * nil indicating linear pacing. */
/* 动画的时间函数 */
@property(nullable, strong) CAMediaTimingFunction *timingFunction;

/* The delegate of the animation. This object is retained for the
 * lifetime of the animation object. Defaults to nil. See below for the
 * supported delegate methods. */
/* 监测动画开始和结束的时间点 */
@property(nullable, strong) id  delegate;

/* When true, the animation is removed from the render tree once its
 * active duration has passed. Defaults to YES. */
/* 这个属性用来控制动画运行结束之后 是否从渲染树中移除当前layer,默认是YES【移除】
一般我们想让动画停留在动画的的终点状态,可以把这个属性设置为NO
 */
@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;

@end

总结:
1、CAAnimation是一个动画抽象类,但是不要直接使用CAAnimation类,而是使用它的子类,画执行过程不在主线程上进行,所以不会阻塞主线程;
2、可以通过重写defaultValueForKey方法更改一些属性的默认值;
3、可以使用动画的时间函数 CAMediaTimingFunction 控制一些简单的动画效果;
4、通过代理监测动画的开始、结束时间;
5、通过removedOnCompletion控制动画结束后是否从渲染树中移除;

CAPropertyAnimation 这里主要对keyPath做一些归纳

KeyPath 描述
transform.scale 比例变化 0 ~ 1
transform.scale.x 宽比例变化 0 ~ 1
transform.scale.y 宽比例变化 0 ~ 1
transform.rotation.x 围绕X轴旋转 0 ~ 2*M_PI
transform.rotation.y 围绕Y轴旋转 0 ~ 2*M_PI
transform.rotation.z 围绕Z轴旋转 0 ~ 2*M_PI
cornerRadius 圆角变化 0 ~ 2*MAX(width,height)
backgroundColor 颜色变化,透明度不变 AnyColor.cgColor
opacity 透明度变化 0 ~ 1
bounds 大小变化,中心不变 CGRect
position 中心变化 CGPoint
position.x 中心X变化 CGFloat
position.y 中心Y变化 CGFloat
contents 内容变化 如ImageView.image image.cgImage
borderWidth 边框宽 0 ~
@interface CAPropertyAnimation : CAAnimation
...

/* additive【添加、附加】 default NO
设置一个抖动的动画:如下
_animView = [[UIView alloc] initWithFrame:CGRectMake(150, 100, 40, 40)];

tranferAnim.values = @[@0,@100,@(-100),@100,@0];
tranferAnim.keyTimes = @[@0,@(1/6.),@(3/6.),@(5/6.),@1];
tranferAnim.additive = YES;
等价于
CGFloat x = self.animView.center.x;
tranferAnim.values = @[@(x),@(x+100),@(x-100),@(x+100),@(x)];
tranferAnim.keyTimes = @[@0,@(1/6.),@(3/6.),@(5/6.),@1];
tranferAnim.additive = NO;

[self.animView.layer addAnimation:tranferAnim forKey:nil];
解释:【个人的理解,有不对之处欢迎指正】
YES 会把当前改变的值附加到presentLayer的value,presentLayer.keyPath.value = modeLayer.keyPath.value + changeValue; 
NO 会把当前改变的值设置为presentLayer的value,presentLayer.keyPath.value = changeValue;
*/
@property(getter=isAdditive) BOOL additive;

/*
cumulative【累积的】设置动画是否是累加效果 default NO
该属性常与repeatCount一起使用,当设置为YES的时候动画会在上一次的基础上进行,而不是回到初始位置
例如:
    CABasicAnimation *tranferAnim = [CABasicAnimation animationWithKeyPath:@"position.x"];
    tranferAnim.duration = 2.0;
    tranferAnim.fromValue = [NSNumber numberWithDouble:25];
    tranferAnim.toValue = [NSNumber numberWithDouble:100];
    tranferAnim.repeatCount = 3;
    tranferAnim.cumulative = YES;
*/
@property(getter=isCumulative) BOOL cumulative;

/* 该属性值是一个CAValueFunction对象,该对象负责对属性改变的插值计算,系统已经提供了默认的插值计算方式,因此一般无须指定该属性。 */
@property(nullable, strong) CAValueFunction *valueFunction;

@end

你可能感兴趣的:(iOS 动画基础一:CAAnimation和CAPropertyAnimation)