CALayer学习笔记

2020-01-18  本文已影响0人  寻心_0a46

CALayer简介

在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮、一个文本标签、一个文本输入框、一个图标等等,这些都是UIView。

其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层,在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层。

@property(nonatomic,readonly,retain) CALayer *layer; 

当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的图层上,绘图完毕后,系统会将图层拷贝到屏幕上,于是就完成了UIView的显示。换句话说,UIView本身不具备显示的功能,拥有显示功能的是它内部的图层。

CALayer的常用属性

@property CGRect bounds;

属性描述 :层的边界。默认为CGRectZero。可设置动画。

@property CGRect bounds;

@property(nullable, strong) __kindof CALayer *mask;

属性描述 : 一个可选层,通过其alpha用于屏蔽层的内容。通过图层的alpha决定了图层内容和背景的显示量。完全或部分不透明的像素允许底层内容显示,但完全透明的像素会阻止该内容。
此属性的默认值为nil。配置遮罩时,请记住设置遮罩层的大小和位置,以确保其与遮罩层正确对齐。

@property(nullable, strong) __kindof CALayer *mask;

@property CGPoint position;

属性描述 : 父级层中层边界矩形的定位点与之对齐的位置。默认为零点。可设置动画。

@property CGPoint position;

@property CGPoint anchorPoint;

属性描述 : 定义层边界矩形的锚点。可以做成动画。使用单位坐标空间指定此属性的值。此属性的默认值为(0.5,0.5),它表示层边界矩形的中心。视图的所有几何操作都发生在指定的点上。例如,对具有默认锚点的层应用旋转变换会导致该层绕其中心旋转。将锚点更改为一个不同的位置将导致层围绕新点旋转。

@property CGPoint anchorPoint;

@property CGFloat zPosition;

属性描述 :图层在Z轴上的位置。可设置动画。此属性的默认值为0。更改此属性的值将更改屏幕上各层的前到后顺序。与值较低的层相比,值较高的层在视觉上更靠近查看器。这会影响帧矩形重叠的层的可见性。

@property CGFloat zPosition;

zPosition使用示例,例如:要让表视图的某一cell这样显示:

cell = [tableView dequeueReusableCellWithIdentifier:YSCUserCenterTitleCellReuseIdentifier];
cell.layer.zPosition = 10;
Jietu20191127-212056@2x.gif

可以让上部的cell中设置背景的视图底部约束超出cell,但在没有设置zPosition属性时,可能是这样的:

Jietu20191127-212804@2x.gif

@property(getter=isHidden) BOOL hidden;

属性描述 : 如果为true,则不显示层及其子层。默认为“ NO”。可设置动画。

@property(getter=isHidden) BOOL hidden;

@property(nullable, readonly) CALayer *superlayer;

属性描述:接收器的superlayer对象。隐式更改以匹配“sublayers”属性描述的层次结构。

@property(nullable, readonly) CALayer *superlayer;

@property BOOL masksToBounds;

属性描述 : 一个布尔值,指示是否将子层剪裁到层的边界。可设置动画。

@property BOOL masksToBounds;

@property(nullable, strong) id contents;

属性描述 :提供图层内容的对象。可设置动画。

@property(nullable, strong) id contents;

@property CGRect contentsRect;

属性描述 : 单位坐标空间中的矩形,定义应使用的图层内容部分。可设置动画。

@property CGRect contentsRect;

@property CGFloat cornerRadius;

属性描述 : 为图层背景绘制圆角时使用的半径。可设置动画。

@property CGFloat cornerRadius;

@property CGFloat borderWidth;

属性描述 : 层边框的宽度。可设置动画。

@property CGFloat borderWidth;

@property(nullable) CGColorRef borderColor;

属性描述 : 图层边框的颜色。可设置动画。

@property(nullable) CGColorRef borderColor;

@property(nullable) CGColorRef shadowColor;

属性描述 : 图层阴影的颜色。可设置动画。

@property(nullable) CGColorRef shadowColor;

@property float shadowOpacity;

属性描述 : 图层阴影的不透明度,默认为0,取值范围0~1。可设置动画。

@property float shadowOpacity;

@property CGSize shadowOffset;

属性描述 : 阴影偏移。默认为(0,-3)。可设置动画。

@property CGSize shadowOffset;

@property CGSize shadowOffset;

属性描述 : 用于创建阴影的模糊半径。默认为3。可设置动画。

@property CGSize shadowOffset;

@property(nullable) CGColorRef backgroundColor;

属性描述 :接收器的背景颜色。可以做成动画。此属性的默认值为nil。

@property(nullable) CGColorRef backgroundColor;

@property CGFloat rasterizationScale;

属性描述 : 相对于图层的坐标空间,光栅化内容的比例。可设置动画

@property CGFloat rasterizationScale;

@property BOOL shouldRasterize;

属性描述 : 光栅化,指示layer在合成之前是否被渲染为位图的布尔值,可动画。启用shouldRasterize属性会将图层绘制到一个屏幕之外的图像,然后这个图像将会被缓存起来。

如果有很多的子图层或者有复杂的效果应用,开启shouldRasterize就会比重绘所有事务的所有帧划得来得多。但是光栅化原始图像需要时间,而且还会消耗额外的内存。所以需要根据实际情况取舍。单次使用或者视图有变动,shouldRasterize不会有任何用途,反而会牺牲内存。对一个层级复杂的视图做动画时,可以启用shouldRasterize避免GPU每帧都重新合成。

调试方法:

xcode开发工具提供的常用的测量方式:

Xcode->Debug->View Debuging->Rendering->Color Offscrenn-rended Yellow可以为触发了离屏渲染的layer着黄色。

Xcode->Debug->View Debuging->Rendering->Hits Green and Misses Red
这个指标可以反映我们通过尝试开启shouldRasterize提升性能的时候是不是达到了预期效果。

当使用shouldRasterize属性的时候,耗时的图层绘制会被缓存,然后当做一个简单的扁平图片呈现。当缓存再生的时候这个选项就用红色对栅格化图层进行了高亮,缓存被重复使用的话就会以绿色进行高亮。如果缓存频繁再生的话(红色太多),就意味着栅格化可能会有负面的性能影响了。

@property BOOL shouldRasterize;

设置涂层阴影的代码示例:

///设置涂层阴影
- (void)setLayerShadowToView:(UIView *)theView withColor:(UIColor*)color withOffset:(CGSize)offset radius:(CGFloat)radius {
    theView.layer.shadowColor = color.CGColor;
    //阴影偏移,默认(0, -3)
    theView.layer.shadowOffset = offset;
    //阴影半径,默认3
    theView.layer.shadowRadius = radius;
    //阴影不透明度
    theView.layer.shadowOpacity = 1;
    //光栅化
    theView.layer.shouldRasterize = YES;
    theView.layer.rasterizationScale = [UIScreen mainScreen].scale;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    UIView *view = [[UIView alloc]initWithFrame:CGRectZero];
    view.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:view];
    [view mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self.view);
        make.size.mas_equalTo(CGSizeMake(100, 100));
    }];
    [self setLayerShadowToView:view withColor:[UIColor blackColor] withOffset:CGSizeMake(0, 0) radius:10.0];
}

屏幕快照 2019-10-30 下午10.01.14.png

CALayer的常用函数

- (void)removeFromSuperlayer;

函数描述 : 将层与其超层分离。可以使用此方法从层的层次结构中删除一个层(及其所有子层)。此方法更新超层的子层列表并将该层的超层属性设置为nil。

- (void)removeFromSuperlayer;

CALayer关于动画的常用函数

- (void)addAnimation:(CAAnimation *)anim forKey:(nullable NSString *)key;

函数描述 : 在层上附加一个动画对象。通常,这是通过CAAnimation对象的操作隐式调用的。

“key”可以是任何字符串,这样每个唯一的key每层只添加一个动画。特殊的key“transition”是自动用于过渡动画。nil指针也是一个有效的键。

如果动画的“duration”属性为0或负值,则会给它默认的持续时间,否则为“animationDuration”事务属性的值或0.25秒。

动画在被添加到图层之前会被复制,所以任何对“anim”的后续修改都不会有影响,除非它被添加到另一个图层。

参数 :

anim : 要添加到渲染树的动画。此对象由渲染树复制,而不是引用。因此,对对象的后续修改不会传播到渲染树中。

key : 标识动画的字符串。每一个唯一的key只有一个动画被添加到该层。特殊的key kCATransition自动用于过渡动画。您可以为该参数指定nil。

- (void)addAnimation:(CAAnimation *)anim forKey:(nullable NSString *)key;

- (void)removeAllAnimations;

函数描述 : 删除所有附加到该层的动画。

- (void)removeAllAnimations;

- (void)removeAnimationForKey:(NSString *)key;

函数描述 : 使用指定的key移除动画对象。

参数 :

key : 要移除的动画的标识符。

- (void)removeAnimationForKey:(NSString *)key;

CAGradientLayer

CAGradientLayer继承CALayer,可以设置渐变图层。

例如设置视图背景渐变色的代码示例:

- (void)setGradualChangeColorView:(UIView *)view{
    
    //CAGradientLayer继承CALayer,可以设置渐变图层
    CAGradientLayer *grandientLayer = [[CAGradientLayer alloc] init];
    grandientLayer.frame = view.bounds;
    [view.layer addSublayer:grandientLayer];
    [view.layer insertSublayer:grandientLayer atIndex:0];
    //设置渐变的方向 左上(0,0)  右下(1,1)
    grandientLayer.startPoint = CGPointZero;
    grandientLayer.endPoint = CGPointMake(0.0, 1.0);
    //colors渐变的颜色数组 这个数组中只设置一个颜色是不显示的
    grandientLayer.colors = @[(id)[UIColor redColor].CGColor, (id)[UIColor greenColor].CGColor];
    grandientLayer.type = kCAGradientLayerAxial;
    
}
- (void)viewDidLoad {

    [super viewDidLoad];
    UIView *view = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 50, CGRectGetMidY(self.view.frame) - 50, 100, 100)];
    [self.view addSubview:view];
    [self setGradualChangeColorView:view];
  
}
屏幕快照 2019-10-30 下午10.50.18.png

CAAnimation

CAAnimation,核心动画中动画的抽象超类。继承自NSObject,遵循了NSSecureCoding、 NSCopying,、CAMediaTiming,、CAAction协议,CAAnimation为CAMediaTiming和CAAction协议提供了基本的支持。不要创建CAAnimation实例:要使核心动画层或SceneKit对象具有动画效果,请创建具体子类CABasicAnimation、CAKeyframeAnimation、CAAnimationGroup或CATransition的实例。

CAAnimation提供的属性

@property(nullable, strong) CAMediaTimingFunction *timingFunction;

属性描述 : 定义动画节奏的可选计时函数。默认为nil,表示线性起搏。

@property(nullable, strong) CAMediaTimingFunction *timingFunction;

@property(nullable, strong) id <CAAnimationDelegate> delegate;

属性描述 : 指定接收者的代理对象。委托对象由接收者保留。这是《高级内存管理编程指南》中描述的内存管理规则的罕见异常。CAAnimation的实例不应该被设置为它自己的代理。这样做(在垃圾收集环境之外)将导致保留周期。

@property(nullable, strong) id <CAAnimationDelegate> delegate;

@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;

属性描述 : 确定动画是否在完成时从目标层的动画中移除。如果为“YES”,动画将在其活动持续时间过后从目标层的动画中移除。默认为“YES”。

@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;

CAAnimation提供的函数

+ (instancetype)animation;

函数描述 : 创建并返回一个新的CAAnimation实例。

+ (instancetype)animation;

+ (nullable id)defaultValueForKey:(NSString *)key;

属性描述 : 指定具有指定键的属性的默认值。如果此方法返回nil,则根据键的声明类型为属性提供一个合适的“zero”默认值。例如,如果key是CGSize对象,则返回大小为(0.0,0.0)的值。对于CGRect,返回一个空矩形。对于CGAffineTransform和CATransform3D,返回适当的单位矩阵。

参数 :

key :接收方属性之一的名称。

返回值 :

指定属性的默认值。如果没有设置默认值,则返回nil。

+ (nullable id)defaultValueForKey:(NSString *)key;

- (BOOL)shouldArchiveValueForKey:(NSString *)key;

属性描述 : 指定是否存档给定键的属性值。由对象的实现encodeWithCoder:调用。对象必须实现键归档。默认实现返回YES。

参数 :

key : 接收方属性之一的名称。

返回值 :

如果要归档指定的属性,则为“YES”,否则为“NO”。

- (BOOL)shouldArchiveValueForKey:(NSString *)key;

CAAnimation提供的代理函数

- (void)animationDidStart:(CAAnimation *)anim;

函数描述 : 当动画开始其活动持续时间时调用。

参数 :

anim : 已启动的CAAnimation对象。

- (void)animationDidStart:(CAAnimation *)anim;

函数描述 :当动画完成其活动持续时间或从其附加到的对象(即层)中移除时调用。如果动画在未被移除的情况下达到其活动持续时间的结尾,则flag'为true。

参数 :

anim :结束的动画对象。

flag : 指示动画是否已通过到达其持续时间的结尾而完成的标志。

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;

CATransition

CATransition继承自CAAnimation,在层状态之间提供动画转换的对象。通过创建并向层中添加CATransition对象,可以在层的状态之间进行转换。默认过渡是交叉淡入,但可以指定与一组预定义过渡不同的效果。

CATransition提供的属性

@property(copy) CATransitionType type;

属性描述 : 指定预定义的转换类型。可能的值以常见的转换类型显示。如果在筛选器属性中指定了自定义转换,则忽略此属性。默认值为kCATransitionFade。

@property(copy) CATransitionType type;
//当图层变得可见或隐藏时,其内容将逐渐消失。
CA_EXTERN CATransitionType const kCATransitionFade
//该层的内容在任何现有内容上滑动到位。公共转换子类型用于此转换。
CA_EXTERN CATransitionType const kCATransitionMoveIn
//该层的内容推动任何现有内容,因为它滑动到位。公共转换子类型用于此转换。
CA_EXTERN CATransitionType const kCATransitionPush
//层的内容按转换子类型指定的方向逐渐显示。公共转换子类型用于此转换。
CA_EXTERN CATransitionType const kCATransitionReveal

@property(nullable, copy) CATransitionSubtype subtype;

属性描述 : 指定一个可选子类型,该子类型指示预定义的基于运动的变换的方向。可能的值显示在公共转换子类型中。默认值为nil。如果在筛选器属性中指定了自定义转换,则忽略此属性。

@property(nullable, copy) CATransitionSubtype subtype;
//过渡从层的右侧开始。
CA_EXTERN CATransitionSubtype const kCATransitionFromRight
//过渡从层的左侧开始。
CA_EXTERN CATransitionSubtype const kCATransitionFromLeft
//过渡从层的顶部开始。
CA_EXTERN CATransitionSubtype const kCATransitionFromTop
//过渡从层的底部开始。
CA_EXTERN CATransitionSubtype const kCATransitionFromBottom

@property float startProgress;

属性描述 : 指示接收器的起点,作为整个转换的一部分。合法值是介于0.0和1.0之间的数字。例如,要在转换过程的一半开始,请将startProgress设置为0.5。默认值为0。

@property float startProgress;

@property float endProgress;

属性描述 : 指示接收器的终点,作为整个转换的一部分。该值必须大于或等于startProgress,且不大于1.0。如果endProgress小于startProgress,则行为未定义。默认值是1.0。

@property float endProgress;

CATransition简单的代码示例

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    UIButton *transitionBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    [transitionBtn setTitle:@"转场动画" forState:UIControlStateNormal];
    [transitionBtn setBackgroundColor:[UIColor blueColor]];
    transitionBtn.titleLabel.font = [UIFont systemFontOfSize:15];
    [transitionBtn addTarget:self action:@selector(transitionBtnClick) forControlEvents:UIControlEventTouchUpInside];
    
    [self.view addSubview:transitionBtn];
    [transitionBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.view).offset(100);
        make.centerX.equalTo(self.view);
        make.size.mas_equalTo(CGSizeMake(75, 35));
    }];
    
}

//转场动画按钮点击
- (void)transitionBtnClick{
    
    UIView *view = [[UIView alloc]initWithFrame:CGRectZero];
    view.backgroundColor = [UIColor redColor];
    
    CATransition *animation = [CATransition animation];
    animation.delegate = self;
    //动画持续时间
    animation.duration = 0.4;
    //减缓速度,这会导致动画快速开始,然后随着它的进展而缓慢。
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    //动画为推出类型
    animation.type = kCATransitionPush;
    //方向,向上方推出
    animation.subtype = kCATransitionFromTop;
    //添加动画
    [view.layer addAnimation:animation forKey:@"animation1"];
    //布局视图
    [self.view addSubview:view];
    [view mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(self.view.mas_bottom);
        make.size.mas_equalTo(CGSizeMake(SCREEN_WIDTH, 360));
    }];
    
}

简单的推出效果 :


Jietu20200104-152550.gif

CAAnimationGroup

CAAnimationGroup继承自CAAnimation,允许多个动画被分组并同时运行的对象。分组动画在CAAnimationGroup实例指定的时间空间中运行。
分组动画的持续时间没有缩放到它们的CAAnimationGroup的持续时间。相反,动画被剪切到动画组的持续时间。例如,在动画组中分组的10秒动画的持续时间为5秒,只显示动画的前5秒。

动画数组中的动画委托和removedOnCompletion属性目前被忽略。CAAnimationGroup委托确实接收这些消息。

CAAnimationGroup提供的属性

@property(nullable, copy) NSArray<CAAnimation *> *animations;

属性描述 : 要在接收器的时间空间内计算的一组CAAnimation对象。动画同时在接收方的时间空间中运行。

@property(nullable, copy) NSArray<CAAnimation *> *animations;

CAPropertyAnimation

继承自CAAnimation,CAPropertyAnimation,属性动画,通常不直接使用,而是使用CABasicAnimation子类。

CAPropertyAnimation提供的属性

@property(nullable, copy) NSString *keyPath;

属性描述 : 描述要设置动画的属性的键路径。键路径是相对于接收器附加到的层的。

@property(nullable, copy) NSString *keyPath;

@property(getter=isAdditive) BOOL additive;

属性描述 : 是否将动画指定的值添加到当前渲染树值以生成新的渲染树值。如果是,动画指定的值将添加到属性的当前渲染树值中,以生成新的渲染树值。加法函数依赖于类型,YES把更改的值追加到当前的层中 keypath+=value ,NO是把更改的值设置成当前层的值keypath = value。默认为否。

@property(getter=isAdditive) BOOL additive;

@property(getter=isCumulative) BOOL cumulative;

属性描述 : “cumulative”属性影响重复动画生成结果的方式。如果为true,则动画的当前值是上一个重复周期结束时的值,加上当前重复周期的值。如果为false,则该值只是为当前重复周期计算的值。默认为否。

@property(getter=isCumulative) BOOL cumulative;

@property(nullable, strong) CAValueFunction *valueFunction;

属性描述 : 如果非nil,则在将插值设置为动画的目标属性的新表示值之前应用于插值的函数。默认为nil。

@property(nullable, strong) CAValueFunction *valueFunction;

CAKeyframeAnimation

CAKeyframeAnimation,继承自CAPropertyAnimation,为层对象提供keyframe动画功能的对象。使用继承的animationWithKeyPath:方法创建CAKeyframeAnimation对象,指定要在该层上进行动画处理的属性的键路径。然后,您可以指定用于控制计时和动画行为的keyframe值。

对于大多数类型的动画,您可以使用values和keyTimes属性指定keyframe值。在动画期间,Core animation通过在提供的值之间插入来生成中间值。当动画一个坐标点的值时,比如层的位置,你可以为那个点指定一个路径,而不是单独的值。动画的速度由您提供的时间信息控制。

CAKeyframeAnimation提供的属性

@property(nullable, copy) NSArray *values;

属性描述 : 为每个keyframe提供动画功能值的对象数组。keyframe值表示动画必须通过的值。将给定的keyframe值应用到该层的时间取决于动画计时,动画计时由calculationMode、keyTimes和timingFunctions属性控制。keyframe之间的值是使用插值创建的,除非计算模式设置为kCAAnimationDiscrete。

根据属性的类型,可能需要用NSNumber的NSValue对象包装这个数组中的值。对于某些核心图形数据类型,可能还需要在将它们添加到数组之前将它们转换为id。

此属性中的值仅在path属性中的值为nil时使用。

@property(nullable, copy) NSArray *values;

@property(nullable) CGPathRef path;

属性描述 : 要遵循的基于点的属性的路径。对于包含CGPoint数据类型的层属性,分配给该属性的path对象将定义该属性在动画长度内的值。如果为该属性指定一个值,则会忽略values属性中的任何数据。

为动画指定的任何时间值都将应用于用于创建路径的点。路径可以包含定义移动到段、线到段或曲线到段的点。行到段或曲线到段的端点定义keyframe值。然后插值该结束值与前一个值之间的所有其他点。移动到段不定义单独的keyframe值。

动画如何沿着路径进行取决于calculationMode属性中的值。若要沿路径实现平滑、恒定速度的动画,请将“calculationMode”属性设置为kCAAnimationPaced或kCAAnimationCubicPaced。若要创建位置值从关键帧点跳到关键帧点的动画(中间无插值),请使用kCAAnimationDiscrete值。若要通过在点之间插值来沿路径设置动画,请使用kCAAnimationLinear值。

@property(nullable) CGPathRef path;

@property(nullable, copy) NSArray<NSNumber *> *keyTimes;

属性描述 : NSNumber对象的可选数组,定义应用给定keyframe段的时间。数组中的每个值是0.0到1.0之间的浮点数,它定义了应用相应keyframe值的时间点(指定为动画总持续时间的一部分)。数组中的每个后续值必须大于或等于前一个值。通常,数组中的元素数量应与values属性中的元素数量或path属性中的控制点数量匹配。如果他们没有,你的动画时间可能不是你所期望的。

要在数组中包含的适当值取决于calculationMode属性。

如果calculationMode设置为kCAAnimationLinear或kCAAnimationCubic,则数组中的第一个值必须是0.0,最后一个值必须是1.0。所有中间值表示开始和结束时间之间的时间点。

如果calculationMode设置为kCAAnimationDiscrete,则数组中的第一个值必须是0.0,最后一个值必须是1.0。数组中应该比values数组中多一个条目。例如,如果有两个值,那么应该有三个key时间。

如果calculationMode设置为kCAAnimationPaced或kCAAnimationCubicPaced,则忽略此属性中的值。

如果此数组中的值无效或不适合当前计算模式,则忽略它们。

@property(nullable, copy) NSArray<NSNumber *> *keyTimes;

@property(nullable, copy) NSArray<CAMediaTimingFunction *> *timingFunctions;

属性描述 : CamediaImingFunction对象的可选数组。可以使用此数组将“缓入”、“缓出”或自定义计时曲线应用于位于两个关键帧值之间的点。如果“值”属性中的关键帧数为n,则此属性应包含n-1个对象。

如果在keyTimes属性中提供计时信息,则使用此属性指定的计时函数将进一步修改这些值之间的计时。如果未为keyTimes属性指定值,则计时函数将修改动画对象提供的默认计时。

如果还在动画对象的timingFunction属性中指定计时函数,则首先应用该函数,然后应用特定关键帧段的计时函数。

@property(nullable, copy) NSArray<CAMediaTimingFunction *> *timingFunctions;

@property(copy) CAAnimationCalculationMode calculationMode;

属性描述 :calculationMode可能的值有“discrete”、“linear”、“paced”、“cubic”和“cubicPaced”。默认为“ linear”。当设置为paced或cubicPaced时,动画的keyTimes和timingFunctions属性将被忽略并隐式计算。

@property(copy) CAAnimationCalculationMode calculationMode;
//keyframe值之间的简单线性计算。
CA_EXTERN CAAnimationCalculationMode const kCAAnimationLinear
//依次使用每个keyframe值,不计算插值。
CA_EXTERN CAAnimationCalculationMode const kCAAnimationDiscrete
//对线性keyframe值进行插值以在整个动画中产生均匀的速度。
CA_EXTERN CAAnimationCalculationMode const kCAAnimationPaced
//keyframe值之间的平滑样条线计算。。
CA_EXTERN CAAnimationCalculationMode const kCAAnimationCubic
//对三次keyframe值进行插值以在整个动画中产生均匀的速度。
CA_EXTERN CAAnimationCalculationMode const kCAAnimationCubicPaced

@property(nullable, copy) NSArray<NSNumber *> *tensionValues;
@property(nullable, copy) NSArray<NSNumber *> *continuityValues;
@property(nullable, copy) NSArray<NSNumber *> *biasValues;

属性描述 : 对于具有三次计算模式的动画,这些属性提供对插值方案的控制。每个关键帧可能具有与其关联的张力、连续性和偏移值,每个都在范围[-1,1]内(这定义了Kochanek-Bartels样条线)。

tensionValues控制曲线的“紧密度”(正值更紧,负值更圆)。continuityValues控制分段的连接方式(正值表示锐角,负值表示倒角)。biasValues定义曲线出现的位置(正值在控制点之前移动曲线,负值在控制点之后移动曲线)。

每个数组中的第一个值定义与第一个控制点相切的行为,第二个值控制第二个点的切线,依此类推。任何未指定的值默认为zero(如果全部未指定,则提供Catmull Rom样条曲线)。

@property(nullable, copy) NSArray<NSNumber *> *tensionValues;
@property(nullable, copy) NSArray<NSNumber *> *continuityValues;
@property(nullable, copy) NSArray<NSNumber *> *biasValues;

@property(nullable, copy) CAAnimationRotationMode rotationMode;

属性描述 : 定义沿路径设置动画的对象是否旋转以匹配路径切线。可能的值是“auto”和“autoReverse”。默认为nil。未定义在未提供路径对象时将此属性设置为非nil值的效果。`“自动翻转”旋转以匹配切线加180度。

@property(nullable, copy) CAAnimationRotationMode rotationMode;
//物体沿着与路径相切的方向运动。
CA_EXTERN CAAnimationRotationMode const kCAAnimationRotateAuto
//物体以与路径相切的180度移动。
CA_EXTERN CAAnimationRotationMode const kCAAnimationRotateAutoReverse

CAKeyframeAnimation代码片段

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    UIView *view = [[UIView alloc]initWithFrame:CGRectZero];
    view.backgroundColor = [UIColor redColor];
    [self.view addSubview:view];
    [view mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self.view);
        make.size.mas_equalTo(CGSizeMake(100, 100));
    }];
    [self changeViewFrame:view];
    
}

- (void)changeViewFrame:(UIView *)view{
    
    CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"position.x"];

    animation.values = @[@100,@(-100),@100];
    animation.keyTimes = @[@0,@(3/6.),@1];
    //动画持续时间
    animation.duration = 2.f;
    //重复次数(HUGE_VALF为无限重复)
    animation.repeatCount = HUGE_VALF;
    //YES把更改的值追加到当前的present层中 keypath+=value ,NO是把更改的值设置成当前present层的值keypath = value
    animation.additive = YES;
    //true,则动画的当前值是上一个重复周期结束时的值,加上当前重复周期的值。false,则该值只是为当前重复周期计算的值。
    animation.cumulative = NO;
    [view.layer addAnimation:animation forKey:@"shaking"];
    
}

代码效果 :

Jietu20200101-232423.gif

CABasicAnimation

继承自CAPropertyAnimation,为layer属性提供基本的单关键帧动画功能的对象。使用继承的animationWithKeyPath:方法创建CABasicAnimation的实例,指定要在渲染树中设置动画的属性的key路径。例如,可以设置层的标量(即包含单个值)属性(例如其不透明度)的动画。通过设置从0到1的不透明度来淡入层。

定义要在其间插入的特性值的对象。所有选项都是可选的,不应超过两个非零。对象类型应与正在设置动画的属性类型匹配(使用CALayer.h中描述的标准规则)。支持的动画模式有:

“fromValue”和“toValue”都不为nil。在fromValue和toValue之间插入。

“fromValue”和“byValue”不为nil。在“fromValue”和“fromValue”加上“byValue”之间插入。

“byValue”和“toValue”不为nil。在“toValue”减去“byValue”和“toValue”之间插入。

“fromValue”非nil。在“fromValue”和属性的当前表示值之间插入。

“toValue”非nil。在呈现树中属性的层的当前值和“toValue”之间进行插值。

“byValue”非nil。在渲染树中属性的图层当前值与该值加上“byValue”之间进行插值。

CABasicAnimation的属性

@property(nullable, strong) id fromValue;

属性描述 : 定义接收器用于开始插值的值。

@property(nullable, strong) id fromValue;

@property(nullable, strong) id toValue;

属性描述 : 定义接收器用于结束插值的值。

@property(nullable, strong) id toValue;

@property(nullable, strong) id byValue;

属性描述 : 定义接收器用于执行相对插值的值。

@property(nullable, strong) id byValue;

CABasicAnimation动画练习的代码片段

设置单帧位置动画:

///设置单帧位置动画
-(void)creatingAnimatePosition:(UIView *)view{
    // 设定为位置
    CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"position"];
    // 动画选项设定
    animation.duration = 0.4; // 动画持续时间
    animation.repeatCount = HUGE_VALF; // 重复次数(HUGE_VALF为无限重复)
    animation.autoreverses = YES; // 动画结束时执行逆动画
    // 位置
    animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(170.f, 170.f)]; // 开始时的位置
    animation.toValue = [NSValue valueWithCGPoint:CGPointMake(200.f, 200.f)]; // 结束时的位置
    animation.removedOnCompletion = NO;
    // 添加动画
    [view .layer addAnimation:animation forKey:@"scale-layer"];
}

设置单帧缩放动画:

///设置单帧缩放动画
-(void)creatingAnimateScale:(UIView *)view{
    // 设定为缩放
    CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    // 动画选项设定
    animation.duration = 0.4; // 动画持续时间
    animation.repeatCount = HUGE_VALF; // 重复次数(HUGE_VALF为无限重复)
    animation.autoreverses = YES; // 动画结束时执行逆动画
    // 缩放倍数
    animation.fromValue = [NSNumber numberWithFloat:1.0]; // 开始时的倍率
    animation.toValue = [NSNumber numberWithFloat:1.1]; // 结束时的倍率
    animation.removedOnCompletion = NO;
    // 添加动画
    [view .layer addAnimation:animation forKey:@"scale-layer"];
}

设置单帧透明度动画:

///设置单帧透明度动画
-(void)creatingAnimateOpacity:(UIView *)view{
    // 设定为透明度
    CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    // 动画选项设定
    animation.duration = 0.4; // 动画持续时间
    animation.repeatCount = HUGE_VALF; // 重复次数(HUGE_VALF为无限重复)
    animation.autoreverses = YES; // 动画结束时执行逆动画
    // 透明度
    animation.fromValue = [NSNumber numberWithFloat:0.0]; // 开始时的透明度
    animation.toValue = [NSNumber numberWithFloat:1.0]; // 结束时的透明度
    animation.removedOnCompletion = NO;
    // 添加动画
    [view .layer addAnimation:animation forKey:@"scale-layer"];
}

设置单帧背景色动画:

///设置单帧背景色动画
-(void)creatingAnimateBackgroundColor:(UIView *)view{
    // 设定为背景颜色
    CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
    // 动画选项设定
    animation.duration = 0.4; // 动画持续时间
    animation.repeatCount = HUGE_VALF; // 重复次数(HUGE_VALF为无限重复)
    animation.autoreverses = YES; // 动画结束时执行逆动画
    // 背景颜色
    animation.fromValue = (id)[UIColor purpleColor].CGColor; // 开始时的颜色
    animation.toValue = (id)[UIColor orangeColor].CGColor; // 结束时的颜色
    animation.removedOnCompletion = NO;
    // 添加动画
    [view .layer addAnimation:animation forKey:@"scale-layer"];
}

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    //创建4个视图
    NSMutableArray *array= [[NSMutableArray alloc]init];
    for(int i =0; i < 4; i ++) {
        UIView *view = [[UIView alloc]initWithFrame:CGRectZero];
        if(i == 0){
            view.backgroundColor = [UIColor redColor];
            [self creatingAnimatePosition:view];
        }else if(i == 1){
            view.backgroundColor = [UIColor greenColor];
            [self creatingAnimateScale:view];
        }else if(i == 2){
            view.backgroundColor = [UIColor yellowColor];
            [self creatingAnimateOpacity:view];
        }else if(i == 3){
            view.backgroundColor = [UIColor blueColor];
            [self  creatingAnimateBackgroundColor:view];
        }
        
        [self.view addSubview:view];
        [array addObject:view];
    }
    
    [array mas_distributeViewsAlongAxis:MASAxisTypeVertical withFixedItemLength:70 leadSpacing:200 tailSpacing:200];
    [array mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.view);
        make.width.mas_equalTo(70);
    }];
    
}

动画效果 :

Jietu20191223-234555.gif

对keypath提供的简单动画的效果的汇总

//CATransform3D Key Paths
static NSString *kCARotation = @"transform.rotation";            //旋转
static NSString *kCARotationX = @"transform.rotation.x";         //围绕X轴旋转
static NSString *kCARotationY = @"transform.rotation.y";         //围绕Y轴旋转
static NSString *kCARotationZ = @"transform.rotation.z";         //围绕Z轴旋转
//缩放
static NSString *kCAScale = @"transform.scale";                  //缩放
static NSString *kCAScaleX = @"transform.scale.x";               //对X方向进行缩放
static NSString *kCAScaleY = @"transform.scale.y";               //对Y方向进行缩放
static NSString *kCAScaleZ = @"transform.scale.z";               //对Z方向进行缩放
//平移
static NSString *kCATranslation = @"transform.translation";      //平移
static NSString *kCATranslationX = @"transform.translation.x";   //对X方向进行平移
static NSString *kCATranslationY = @"transform.translation.y";   //对Y方向进行平移
static NSString *kCATranslationZ = @"transform.translation.z";   //对Z方向进行平移
//平面
static NSString *kCAPosition = @"position";                      //CGPoint中心点改变位置
static NSString *kCAPositionX = @"position.x";                   //CGPoint中心点X方向改变位置
static NSString *kCAPositionY = @"position.y";                   //CGPoint中心点Y方向改变位置
//CGRect
static NSString *kCABoundsSize = @"bounds.size";                 //自身界限的大小
static NSString *kCABoundsSizeW = @"bounds.size.width";          //自身界限的宽度
static NSString *kCABoundsSizeH = @"bounds.size.height";         //自身界限的高度
static NSString *kCABoundsOriginX = @"bounds.origin.x";          //自身界限的起点X方向
static NSString *kCABoundsOriginY = @"bounds.origin.y";          //自身界限的起点Y方向
//Layer
static NSString *kCAOpacity = @"opacity";                        //透明度
static NSString *kCABackgroundColor = @"backgroundColor";        //背景色
static NSString *kCACornerRadius = @"cornerRadius";              //圆角
static NSString *kCABorderWidth = @"borderWidth";                //边框
static NSString *kCAShadowColor = @"shadowColor";                //阴影颜色
static NSString *kCAShadowOffset = @"shadowOffset";              //偏移量CGSize
static NSString *kCAShadowOpacity = @"shadowOpacity";            //阴影透明度
static NSString *kCAShadowRadius = @"shadowRadius";              //阴影圆角

CASpringAnimation

CASpringAnimation继承自CABasicAnimation,对层的属性应用类似弹簧力的动画。通常使用弹簧动画设置层位置的动画,使其看起来被弹簧拉向目标。层离目标越远,对它的加速度就越大。CASpringAnimation允许控制基于物理的属性,例如弹簧的阻尼和刚度。

CASpringAnimation提供的属性

@property CGFloat mass;

属性描述 : 附着在弹簧末端的物体的质量。默认质量为1。增加该值将增加弹簧效果:附加对象将受到更多的振荡和更大的超调,从而增加沉降持续时间。减小质量将减少弹簧效应:振动减少,超调减小,从而减少沉降持续时间。

@property CGFloat mass;

@property CGFloat stiffness;

属性描述 : 弹簧刚度系数。默认的刚度系数为100。增加刚度可减少振荡次数,并缩短沉降持续时间。减小刚度会增加振荡次数,并增加沉降持续时间。

@property CGFloat stiffness;

@property CGFloat damping;

属性描述 : 定义由于摩擦力应如何阻尼弹簧的运动。阻尼属性的默认值是10。减少这个值可以减少每次振荡的能量损失:动画值将超过toValue,并且使持续时间大于持续时间。增加数值会增加能量损耗:振荡会越来越少,越来越小,沉降时间可能会比持续时间小。

@property CGFloat damping;

@property CGFloat initialVelocity;

属性描述 : 附着在弹簧上的物体的初始速度。默认为0,表示不移动的对象。负值表示从弹簧附着点移动的对象,正值表示朝弹簧附着点移动的对象。

@property CGFloat initialVelocity;

@property(readonly) CFTimeInterval settlingDuration;

属性描述 : 返回要到静止时考虑的弹簧系统所需的估计持续时间。将为当前动画参数计算持续时间。

@property(readonly) CFTimeInterval settlingDuration;

CAReplicatorLayer

CAReplicatorLayer继承自CALayer,是一个Layer容器,添加到容器上的子Layer可以复制若干份;可以设定子Layer复制份数、设定副本之间的距离、透明度、颜色、旋转、位置等,可以使用CAReplicatorLayer对象来基于单一源层构建复杂的布局。

CAReplicatorLayer的属性

@property CFTimeInterval instanceDelay;

属性描述 : 指定复制副本之间的延迟(秒),可设置动画,默认值为0.0,这意味着添加到复制副本的任何动画都将同步。

@property CFTimeInterval instanceDelay;

@property NSInteger instanceCount;

属性描述 : 要创建的副本数,其中包括源图层,默认值为1,不创建额外副本。

@property NSInteger instanceCount;

@property CATransform3D instanceTransform;

属性描述 : 应用于将前一个实例以生成当前实例的转换矩阵。可以做成动画。该矩阵应用于相对于该层中心的位置。默认是单位矩阵。

@property CATransform3D instanceTransform;

@property BOOL preservesDepth;

属性描述 : 定义此层是否将其子层展平到其平面中。如果YES,则该层的行为与CATTransfermLayer相似,并且具有相同的限制。默认值为NO。

@property BOOL preservesDepth;

@property(nullable) CGColorRef instanceColor;

属性描述 : 定义用于复制源对象的颜色。可以做成动画。默认为不透明白色。

@property(nullable) CGColorRef instanceColor;

@property float instanceRedOffset;

属性描述 : 为每个复制的实例定义添加到组件的颜色的红色偏移量,可设置动画。将instanceGreenOffset添加到k-1位置的实例的红色分量中,以生成实例k位置的实例的调制颜色。

@property float instanceRedOffset;

@property float instanceGreenOffset;

属性描述 : 为每个复制的实例定义添加到组件的颜色的绿色偏移量,可设置动画。将instanceGreenOffset添加到k-1位置的实例的绿色分量中,以生成实例k位置的实例的调制颜色。

@property float instanceGreenOffset;

@property float instanceBlueOffset;

属性描述 : 为每个复制的实例定义添加到组件的颜色的蓝色偏移量,可设置动画。将instanceGreenOffset添加到k-1位置的实例的蓝色分量中,以生成实例k位置的实例的调制颜色。

@property float instanceBlueOffset;

@property float instanceAlphaOffset;

属性描述 : 为每个复制的实例定义添加到组件的颜色的透明度移量,可设置动画。将instanceGreenOffset添加到k-1位置的实例的透明度分量中,以生成实例k位置的实例的调制颜色。

@property float instanceAlphaOffset;

简单的震动条示例

@interface TestCodeController ()

@end

@implementation TestCodeController

- (void)viewDidLoad {

    [super viewDidLoad];
    
    UIView *aniView = [[UIView alloc] initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width / 2 - 40, CGRectGetMidY(self.view.frame) , 5, 20)];
    [self.view addSubview:aniView];
    [aniView.layer addSublayer: [self replicatorLayer_Shake]];

}

// 震动条动画
- (CALayer *)replicatorLayer_Shake{
    //初始化层对象
    CALayer *layer = [[CALayer alloc]init];
    //层对象框架矩形
    layer.frame = CGRectMake(0, 0, 10, 32);
    //设置圆角
    layer.cornerRadius = 5.0f;
    //设置层背景色
    layer.backgroundColor = [UIColor redColor].CGColor;
    //定义层边界矩形的定位点,可设置动画
    layer.anchorPoint = CGPointMake(0.5, 0.5);
    // 添加一个对Y方向进行缩放的基本动画
    [layer addAnimation:[self scaleYAnimation] forKey:@"scaleAnimation"];
    
    //初始化复制层
    CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer];
    //复制层框架矩形
    replicatorLayer.frame = CGRectMake(0, 0, 80, 80);
    //要创建的副本数
    replicatorLayer.instanceCount = 3;
    //复制矩阵
    replicatorLayer.instanceTransform =  CATransform3DMakeTranslation(20, 0, 0);
    //指定复制副本之间的延迟(秒)
    replicatorLayer.instanceDelay = 0.2;
    //为每个复制的实例定义添加到组件的颜色的绿色偏移量,可设置动画
    replicatorLayer.instanceGreenOffset = 10;
    //将层对象添加到复制层容器
    [replicatorLayer addSublayer:layer];
    //返回复制层容器
    return replicatorLayer;
}

//对Y方向进行缩放的基本动画
- (CABasicAnimation *)scaleYAnimation{
    //对Y方向进行缩放的基本动画
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.scale.y"];
    //缩放结束值
    anim.toValue = @0.1;
    //动画持续时间
    anim.duration = 0.4;
    //动画完成后是否在层中移除
    anim.removedOnCompletion = NO;
    //动画结束是否执行逆动画
    anim.autoreverses = YES;
    //动画重复次数为无限重复
    anim.repeatCount = MAXFLOAT;
    //返回/对Y方向进行缩放的基本动画
    return anim;
}

@end

效果如图:

Jietu20200924-162759.gif
上一篇 下一篇

猜你喜欢

热点阅读