iOS CoreAnimation(一) - 基础知识

相关文献:
iOS CoreAnimation(一) - 基础知识
iOS CoreAnimation(二) - CALayer/UIBezierPath
iOS CoreAnimation(三) - CAEmitterLayer粒子图层

本文主要内容:
1.了解CoreAnimation
2.UIView与CALayer
3.图层树/表示树/渲染树
4.hitTest
5.了解核心动画类的属性
6.核心动画KeyPath表

一、了解CoreAnimation

CPU(Central Processing Unit-中央处理器)是一块超大规模的集成电路,是一台计算机的运算核心(Core)和控制核心( Control Unit)。它由运算器(ALU)和控制器(CU)两大部件组成。此外,还有若干个寄存器和高速缓冲存储器及实现它们之间联系的数据、控制及状态总线。CPU的功能主要是解释计算机指令以及处理计算机软件中的数据。

cpu

GPU(Graphics Processing Unit-图形处理器);又称显示核心、显卡、视觉处理器、显示芯片或绘图芯片)是一种专门在个人电脑、工作站、游戏机和一些移动设备(如平板电脑、智能手机等)上图像运算工作的微处理器。GPU不仅在图像处理中应用广泛,还在科学计算、密码破解、数值分析、大数据处理、金融分析等需要并行运算的领域中广为应用。

GPU

CoreAnimation是对OpenGL/Metal 与 CoreGraphics进行封装的专门处理图形的一套API接口,简化了图形图像处理需要大量的计算以节约开发者的开发时间。其底层就是让GPU去做事情。

架构
CoreAnimation分类
核心动画类

CAAnimation是所有动画对象的父类(抽象类,虚类),实现CAMediaTiming协议,负责控制动画的时间、速度和时间曲线等等,是一个抽象类,不能直接使用。

  • CAAnimationGroup: 动画组,可以将很多种动画合并到一起,组成动画效果。
  • CATransition: 转场动画效果。
  • CAKeyframeAnimation: 关键帧动画效果。values : 一个NSArray对象。里面的元素称为”关键帧”(keyframe),动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧。简单理解为,很多动画帧执行。
  • CABasicAnimation: 基础动画,简单常见的动画效果。
  • CASpringAnimation: iOS9.0之后新增,弹簧效果的动画,是CABasicAnimation的子类。

二、UIView与CALayer(视图和图层)

1.UIView与CALayer的关系:
  • 1.UIView是UIKit框架中的, 继承于UIRespond,View可以响应触摸事件
    CALayer是QuartzCore框架里面CoreAnimation中的,继承自NSObject, Layer不响应事件
  • 2.UIView有个只读的layer属性,称为根Layer,UIView的图层是由layer来生成的,所以对UIView的frame等属性的修改本质上是对layer的属性的修改。
  • 3.可以给UIView添加子Sublayer,[self.layer addSublayer:],效果像addSubview一样显示,但sublayer在修改position、size、opacity等属性时会产生隐式动画(默认有个动画效果), 这就没有操作subview方便。
  • 4.使用系统提供的layer和自定义layer都可添加为subLayer,但需要调用[layer setNeedsDisplay]。 对于自定义layer方式有三个:设置layer代理、自定义CALayer子类。
  • 5.UIView是根layer的代理。
view与layer关系

分工明确:view去相应事件;layer去做显示。

2.了解UIView和CALayer的属性
UIView的属性
CALayer的属性

值得注意的是:

  • 1.在CALayer中很少使用frame属性,因为frame本身不支持动画效果,通常使用boundsposition代替
  • 2.CALayer中透明度使用opacity表示而不是alpha;中心点使用position而不是center
  • 3.anchorPoint属性是图层的锚点,范围在(0-1,0-1)表示在x、y轴的比例,这个点永远可以同position(中心点)重合,当图层中心点固定后,调整anchorPoint。即可达到调整图层显示位置的作用(因为它永远和position重合)

positionanchorPoint 在图层中的关系:

anchorPoint的默认值为(0.5,0.5),也就是anchorPoint默认在layer的中心点。
默认情况下,使用addSublayer函数添加layer时,如果已知layerframe值,根据上面的结论,那么position的值便可以用下面的公式计算:

position.x = frame.origin.x + anchorPoint.x * bounds.size.width;  
position.y = frame.origin.y + anchorPoint.y * bounds.size.height;
面试题
面试题

三、图层树/表示树/渲染树 (Layer Tree / Presentation Tree / Render Tree)

  • 图层树(Layer Tree):包含每一层图层里面对象模型的值(开发者设置的一些值)。

  • 表示树(呈现树Presentation Tree):比如当前动画要发生了,它就包含了当前动画将要显示的值。比如一个layer需要改变颜色,它不会立马更新(隐式动画),需要等待图层树完了之后,表示树才会更新出来。

所以图层树与表示树之间会有一个滞后性。

  • 渲染树(Render Tree):它使用的是表示树的值,主要对独立的UI渲染动作,每一次渲染都是单独的线程来做事。

LayerTree -> PresentationTree滞后性的案例:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 平移动画
    CABasicAnimation *animation = [CABasicAnimation animation];
    animation.keyPath = @"position.y";
    animation.toValue = @600;
    animation.duration = 1;
    
    [_redView.layer addAnimation:animation forKey:nil];
}

执行动画平移完了之后发现redView回到初始的位置。

解决动画恢复到初始位置:

animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
/**
KCAFil1ModeForwards:动画结束后,1ayer会一直保持动画最后的状态
KCAFi11ModeBackwards:在动画开始前,将动画加入一个Layer, layer便立即进入动画的初始状态井等待动画开始.(设置之后就显示动画第一帧)
kCAFillModeBoth: kCAFillModeForwards & kCAFillModeBackwards
kCAFil1ModeRemoved: 默认,
*/

四、hitTest

layer的hitTest

view的hitTest

#import "RedView.h"
@implementation RedView
/**
 - (UIview*)hitTest: (CGPoint )point withEvent: (UIEvent *)event
 point:在接收器局部坐标系中的点
 event:系统保证调用此方法事简。
 Hit Test 调用顺序
 touch -> UIApplication -> UIWindow -> UIViewController -> UIView -> subview ->... -> 合适的View
 事件的传递顺序刚好和与之相反。
 
 常见UIview 不响应事件的处理有那些?
 1.view.userInteractionEnabled = NO:
 2.view.hidden = yes;
 3.view.alpha < 0.05:
 4. view #BitsuperViewtibounds
 */
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    // 1.是否相应时间的必然条件
    if (self.userInteractionEnabled == NO || self.alpha < 0.05 || self.hidden == YES) {
        return  nil;
    }
    // 2,touch的point在self.bounds内容
    if ([self pointInside:point withEvent:event]) {
        for(UIView *subview in self.subviews) {
            // 进行坐标转换
            CGPoint coverPoint = [subview convertPoint: point fromView:self];
            UIView *hittestView = [subview hitTest:coverPoint withEvent:event];
            if (hittestView) {return hittestView;}
        }
        return self;
    }
    return nil;
}
@end

注意:常见UIview不响应事件的处理有那些?
1.view.userInteractionEnabled = NO:
2.view.hidden = YES;
3.view.alpha < 0.05:
4.超出view边界不响应

HitTest运用场景:

事件穿透
子视图超出父视图
子视图超出父视图

五、CoreAnimation简单使用

  • CABasicAnimation
#import "ViewController.h"
/*
 动画添加步骤:
 1.找演员CALayer,确定动画主角
 2.写剧本CAAnimation,规定动画怎么样变换
 3.开拍AddAnimation,开始执行
 */
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *redView;
@property (nonatomic,strong) CALayer *layer;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    CALayer *layer = [CALayer layer];
    layer.frame = CGRectMake(100, 100, 100, 100);
    layer.backgroundColor = [UIColor greenColor].CGColor;
    _layer = layer;
    [self.view.layer addSublayer:layer];
}


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //动画1
    CABasicAnimation *animation = [CABasicAnimation animation];
    animation.keyPath = @"position.y";
    animation.toValue = @600;
    animation.duration = 1;
    
    //解决动画恢复到初始位置
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;
    
    
    [_redView.layer addAnimation:animation forKey:nil];
    
    
    //动画2
    //begin a new transaction
    [CATransaction begin];
    
    //set the animation duration to 1 second
    [CATransaction setAnimationDuration:2.0];
    
    _layer.backgroundColor = [UIColor orangeColor].CGColor;
    
    [CATransaction setCompletionBlock:^{
        //rotate the layer 90 degrees
        CGAffineTransform transform = self.layer.affineTransform;
        transform = CGAffineTransformRotate(transform, M_PI_2);
        self.layer.affineTransform = transform;
        
    }];
    
    //commit the transaction
    [CATransaction commit];
}
  • CAKeyframeAnimation
#import "ViewController.h"
#define angleToRadians(angle) ((angle)/180.0 * M_PI) // 度数转弧度
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *pigView;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 图片抖动
    CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
    anim.keyPath = @"transform.rotation";
    anim.values = @[@angleToRadians(-3),
                     @angleToRadians(5),
                     @angleToRadians(-3),
                     ];
    anim.autoreverses = YES;
    anim.speed = 2;
    anim.duration = 1;
    anim.repeatCount = MAXFLOAT;
    [_pigView.layer addAnimation:anim forKey:nil];

}
@end

六、了解核心动画类的属性

1.CAMediaTiming协议

不只是CAAnimation遵循CAMediaTiming协议,CALayer也遵循这个协议,所有在一定程度上我们可以通过控制layer本身的协议属性来控制动画节奏。

CAMediaTiming协议中定义了时间,速度,重复次数等。属性定义如下:

  • beginTime-> 用来设置动画延时,若想延迟1秒,就设置为CACurrentMediaTime()+1,其中CACurrentMediaTime()为图层当前时间。
  • duration -> 动画的持续时间。
  • speed-> 动画速率,决定动画时间的倍率。当speed为2时,动画时间为设置的duration*0.5
  • timeOffset -> 动画时间偏移量。比如设置动画时长为3秒,当设置timeOffset为1.5时,当前动画会从中间位置开始,并在到达指定位置时,走完之前跳过的前半段动画。
  • repeatCount -> 动画的重复次数。
  • repeatDuration -> 动画的重复时间。
  • autoreverses -> 动画由初始值到最终值后,是否反过来回到初始值的动画。如果设置为YES,就意味着动画完成后会以动画的形式回到初始值。
  • fillMode -> 决定当前对象在非动画时间段的行为.比如动画开始之前,动画结束之后。

fillMode详细说明:试想这样一个问题:在beginTime非0(即动画未真正执行之前),以及removeOnCompletion被设置为NO的动画结束时,我们会遇到这样一个问题:被设置动画的属性应该是什么值?
一种可能是属性与动画没被添加之前保持一致,还有一种可能是保持动画开始之前那一帧或者动画结束那一帧,这就是所谓的填充。
CAMediaTiming的fillMode用来控制填充效果,它是一个NSString类型,有四种常量可供使用:
kCAFillModeRemoved (default) ,动画开始前和结束后,动画对图层都没有影响,图层依然保持初始值;
kCAFillModeForwards 动画结束后,图层一直保持动画后的最终状态;
kCAFillModeBackwards 动画开始前,只要加入动画就会处于动画的初始状态;
kCAFillModeBoth综合了kCAFillModeForwards与kCAFillModeBackwards特性。
(动画加入图层到真正执行动画的时间段里,图层保持动画初始状态;动画结束之后保持动画最终状态)

2.CAAnimation 基础类

CAAnimation核心动画基础类,不能直接使用遵循了CAMediaTiming协议,增加了CAAnimationDelegate的代理属性等。关于它的定义如下:

@interface CAAnimation : NSObject<NSSecureCoding, NSCopying, CAMediaTiming, CAAction>
@property(nullable, strong) CAMediaTimingFunction *timingFunction;
@property(nullable, strong) id <CAAnimationDelegate> delegate;
@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;
@end
  • removedOnCompletion -> 是否让图层保持显示动画执行后的状态,默认为YES,也就是动画执行完毕后从涂层上移除,恢复到执行前的状态,如果设置为NO,并且设置fillMode为kCAFillModeForwards,则保持动画执行后的状态
  • delegate -> 代理。
  • timingFunction -> 控制动画的节奏、动画缓冲属性。动画实际上就是在一段时间内随着某个特定速率执行变化的过程,现实中的任何物体都会在运动中经历加速或者减速的过程,而不是速度骤变;因此,CoreAnimation也内嵌了一系列标准的缓冲函数来使动画看起来更平滑自然,这就是我们要说到的动画缓冲。

timingFunction的值:
kCAMediaTimingFunctionLinear 默认,匀速执行动
kCAMediaTimingFunctionEaseIn 慢进快出
kCAMediaTimingFunctionEaseOut 快进慢出
kCAMediaTimingFunctionEaseInEaseOut 慢进慢出,中间加速
kCAMediaTimingFunctionDefault 默认.
当然也可通过自定义创建CAMediaTimingFunction。

CAAnimation的delegate代理方法如下几个:

//动画开始时执行的回调
- (void)animationDidStart:(CAAnimation *)anim;
//动画结束后执行的回调
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
3.CAPropertyAnimation 属性动画

CAPropertyAnimation 是一个抽象类,不可直接使用。不能直接用于实现CALayer动画操作,但是它的类定义中增加用于设置CALayer可被实现动画的属性keyPath

+ (instancetype)animationWithKeyPath:(NSString *)path;该方法仅需要一个参数,该参数只是一个字符串的值,指定CALayer的动画属性名,该设置属性动画控制CALayer的哪个动画属性持续的改变。

CAPropertyAnimation属性具体如下:

  • keyPath -> CALayer的某个属性名,并通过这个属性的值进行修改,达到相应的动画效果。
  • additive -> 属性动画是否以当前动画效果为基础,默认为NO。
  • cumulative -> 指定动画是否为累加效果,默认为NO。
  • valueFunction -> 此属性配合CALayer的transform属性使用。
  • affineTransform -> CGAffineTransform对象(变换矩阵),该对象代表CALayer执行X,Y两个维度(也就是平面)上的旋转,缩放,位移,斜切,镜像等变换矩阵。
  • transform -> 该属性值指定一个CATransform3D对象,该对象代表对CALayer执行X,Y,Z三个维度(三维空间)中的旋转,缩放,位移,斜切,镜像等变换矩阵。很明显如果只是对CALayer进行平面上的变换,指定普通的affineTransform属性即可,如果要对CALayer执行三维空间的变化,则需要指定transform属性

关于变形矩阵我的文章里有介绍CALayer中仿射变换

CABasicAnimation基础动画,通过keyPath对应属性进行控制,需要设置fromValue以及toValue。添加属性如下:
fromValue -> keyPath相应属性的初始值。
toValue -> keyPath相应属性的结束值。
byValue -> 在不设置toValue时,toValue = fromValue + byValue,也就是在当前的位置上增加多少。

4.CAAnimationGroup动画组

能将多个动画组合在一起,如平移、缩放、旋转等效果组合在一起做出更炫酷的的效果。

  • animations -> 所有动画效果元素的数组。
NSLog(@"动画执行前redView.frame:%@", NSStringFromCGRect(self.redView.frame));

 //平移
CABasicAnimation *transition = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
transition.toValue = @(300);
//旋转
CABasicAnimation *rotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
rotation.toValue = @(M_PI);
//缩放
CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scale.toValue = @(0.2);

//添加组动画
CAAnimationGroup *group = [CAAnimationGroup animation];
//注意这里动画的效果 要设置成group的
group.duration = 2.0;
group.animations = @[rotation, scale, transition];
group.removedOnCompletion = NO;
group.fillMode = kCAFillModeForwards;

[self.redView.layer addAnimation:group forKey:nil];
5.CABasicAnimation基础动画

CABasicAnimation即基础动画,在指定可动画属性后,动画会按照预定的参数持续一定时间由初始值变换为终点值。
其实CABasicAnimation就相当于只有开始和结束两个帧的特殊关键帧动画。

CABasicAnimation的属性:
CABasicAnimation继承链条:CABasicAnimation-> CAPropertyAnimation -> CAAnimation -> NSObject && 遵循CAMediaTiming协议

  • fromValue -> 起始值
  • toValue -> 结束值
  • byValue -> keyPath属性的变化值

CABasicAnimation的简单使用:

@interface TestBacicAnimation1VC ()<CAAnimationDelegate>
@property (nonatomic,strong) CALayer *colorLayer;
@end

@implementation TestBacicAnimation1VC

- (void)viewDidLoad {
    [super viewDidLoad];
    //创建显示颜色的图层,添加于视图控制器的View上
    CALayer *colorLayer = [CALayer layer];
    colorLayer.frame = CGRectMake(50, 50, 100, 100);
    colorLayer.backgroundColor = [UIColor redColor].CGColor;
    self.colorLayer = colorLayer;
    [self.view.layer addSublayer:colorLayer];
}

- (IBAction)changeColor:(UIButton *)sender{
    //步骤1:创建动画
    CABasicAnimation *animation = [CABasicAnimation animation];
    animation.keyPath = @"backgroundColor";
    //步骤2:设定动画属性
    animation.autoreverses = NO;
    animation.duration = 0.25;
    animation.repeatCount = 1;
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;
    animation.delegate = self;
    UIColor *randomColor = [UIColor randomColor];  //自定义获取随机色的方法
    animation.toValue = (__bridge id _Nullable)(randomColor.CGColor);
    //步骤3:添加动画到图层
    [self.colorLayer addAnimation:animation forKey:@"keyPath_backgroundColor"];
}

- (void)animationDidStop:(CABasicAnimation *)anim finished:(BOOL)flag{
    //禁用隐式动画
    [CATransaction begin];
    [CATransaction setDisableActions:true];
    self.colorLayer.backgroundColor = (__bridge CGColorRef)anim.toValue;
    [CATransaction commit];
}

关闭隐式动画:
对独立图层(即非UIView的关联图层,类似上述例子中的colorLayer)做更新属性的显式动画,我们需要设置一个事务来禁用图层行为,否则动画会发生两次,一次是因为显式的CABasicAnimation,另一次是因为隐式动画,从而导致我们看到的动画异常。

6.CAKeyframeAnimation关键帧动画

CAKeyframeAnimation 关键帧动画,同样通过·keyPath·对应属性进行控制,但它可以通过·values·或者·path·进行多个阶段的控制。

CAKeyframeAnimation属性如下:
CAKeyframeAnimation继承链条:CAKeyframeAnimation-> CAPropertyAnimation -> CAAnimation -> NSObject && 遵循CAMediaTiming协议

  • values -> 关键帧组成的数组,动画会依次显示其中的每一帧。
  • path-> 关键帧路径,动画进行的要素,优先级比values高,但是只对CALayeranchorPointposition起作用。(如果你设置了path,那么values将被忽略)
  • keyTimes -> 每一帧对应的时间,如果不设置,则各关键帧平分设定时间。
  • timingFunctions -> 每一帧对应的动画节奏。
  • calculationMode -> 动画的计算模式,系统提供了对应的几种模式。
  • tensionValues -> 动画张力控制。
  • continuityValues -> 动画连续性控制。
  • biasValues -> 动画偏差率控制。
  • rotationMode -> 动画沿路径旋转方式,系统提供了两种模式。

关键帧动画的实现方式实际分为两种:
1.通过values设置关键帧属性值数组;
2.通过path设置关键帧路径,而且此种方式的优先级较高;

  • 通过values设置关键帧
    实现这样的关键帧动画:创建一个紫色滑块在四个坐标点之间滑动;具体的代码实现如下:
- (void)viewDidLoad {
    [super viewDidLoad];
    //创建测试帧动画的紫色图层
    UIView *purpleView = [UIView new];
    purpleView.frame = CGRectMake(0, 0, 50, 50);
    purpleView.center = CGPointMake(50, 100);
    purpleView.backgroundColor = [UIColor purpleColor];
    [self.view addSubview:purpleView];
    
    //步骤1:创建动画
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
    animation.keyPath = @"position";
    //步骤2:设置动画关键帧数据
    NSValue *value1 = [NSValue valueWithCGPoint:CGPointMake(50, 100)];
    NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(kDeviceWidth -50, 100)];
    NSValue *value3 = [NSValue valueWithCGPoint:CGPointMake(kDeviceWidth -50, kDeviceWidth- 100)];
    NSValue *value4 = [NSValue valueWithCGPoint:CGPointMake(50, kDeviceWidth -100)];
    NSValue *value5 = [NSValue valueWithCGPoint:CGPointMake(50, 100)];
    animation.values = @[value1,value2,value3,value4,value5];
    //步骤3:设定动画属性
    animation.repeatCount = MAXFLOAT; //重复执行
    animation.autoreverses = NO;
    animation.removedOnCompletion = NO;
    animation.duration = 4;
    //animation.keyTimes = @[@(0), @(1 / 10.0), @(5 / 10.0), @(9 / 10.0), @(1) ];
    animation.timingFunctions  = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],
                                   [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn],
                                   [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut],
                                   [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];

    [purpleView.layer addAnimation:animation forKey:nil];
}
  • path设置关键帧路径
    实现🚗沿着轨道行走的动画:
/*
 贝塞尔曲线:1.数据点(起点终点);2.控制点
 */
#import "ViewController.h"

@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    [self test];
}

- (void)test{
    //1.定义贝塞尔曲线
    UIBezierPath *path = [UIBezierPath bezierPath];
    //起始点
    [path moveToPoint:CGPointMake(20, 200)];
    //终点 和 控制点
    [path addCurveToPoint:CGPointMake(300, 200) controlPoint1:CGPointMake(100, 100) controlPoint2:CGPointMake(200, 300)];
    
    //2.为了显示贝塞尔曲线->shapeLayer(显示路径)
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    shapeLayer.path = path.CGPath;
    shapeLayer.fillColor = nil;
    shapeLayer.strokeColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:shapeLayer];
    
    //添加图层
    CALayer *carLayer = [CALayer layer];
    carLayer.frame = CGRectMake(15, 200-18,36,36);
    //寄宿图
    carLayer.contents = (id)[UIImage imageNamed:@"car.png"].CGImage;
    carLayer.anchorPoint = CGPointMake(0.5, 0.8); // 锚点
    [self.view.layer addSublayer:carLayer];
    
    // 让轨道和🚗图层结合起来
    //关键帧动画
    CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
    //路径! keypath
    anim.keyPath = @"position";
    //path
    anim.path = path.CGPath;
    anim.duration = 4.0;
    anim.rotationMode = kCAAnimationRotateAuto;
    anim.repeatCount = MAXFLOAT;
    
    [carLayer addAnimation:anim forKey:nil];
}
@end
7.CATransition 转场动画
  • type -> 转场动画类型。
    kCATransitionFade:交叉淡化过渡
    kCATransitionPush:新视图吧旧视图
    kCATransitionMoveIn:新视图移到旧视图上面
    kCATransitionReveal:将旧视图移开,显示下面的视图
    用字符串表示:
    pageCurl:向上翻页效果
    pageUnCurl:向下翻页效果
    cube:立方体翻滚效果
    oglFlip:上下左右翻转效果
    rippleEffect:波纹
    suckEffect:吮吸
    flipFromLeft:左翻转
    flipFromRight:右翻转
    suckEffect:收缩效果,如一块布被抽走
    rippleEffect:水滴效果
    cameraIrisHollowOpen:相机镜头打开效果
    cameraIrisHollowClose:相机镜头关闭效果

  • subtype -> 转场动画方向。
    kCATransitionFromRight 从右向左,
    kCATransitionFromTop 从上向下,
    kCATransitionFromLeft 从左向右,
    kCATransitionFromBottom 从下向上

  • startProgress -> 动画起点进度(整体的百分比)。
  • endProgress -> 动画终点进度(整体的百分比)。
  • filter -> 自定义转场。
  • duration -> 动画执行时间
  • timingFunction -> 动画的运动轨迹,用于变化起点和终点之间的插值计算,形象点说它决定了动画运行的节奏,比如是均匀变化(相同时间变化量相同)还是先快后慢,先慢后快还是先慢再快再慢
    kCAMediaTimingFunctionLinear 线性,即匀速
    kCAMediaTimingFunctionEaseIn 先慢后快
    kCAMediaTimingFunctionEaseOut 先快后慢
    kCAMediaTimingFunctionEaseInEaseOut 先慢后快再慢
    kCAMediaTimingFunctionDefault 实际效果是动画中间比较快
@interface TestTransition1VC ()

@property (nonatomic,strong) UIImageView *imageView;
@property (nonatomic,strong) NSArray *images;

@property (nonatomic, copy) NSString *type;
@property (nonatomic, copy) NSString *subtype;

@end

@implementation TestTransition1VC

- (void)viewDidLoad {
    [super viewDidLoad];
    self.images = @[[UIImage imageNamed:@"tree_spring"],
                    [UIImage imageNamed:@"tree_summer"],
                    [UIImage imageNamed:@"tree_autumn"],
                    [UIImage imageNamed:@"tree_winter"]];
    
    self.type = kCATransitionFade;
    self.subtype = kCATransitionFromRight;
}

- (void)perforomTransitionAnimation{
    CATransition *transition = [[CATransition alloc] init];
    transition.type = _type;
    transition.subtype = _subtype;
    transition.duration = 0.5;
    [self.imageView.layer addAnimation:transition forKey:nil];
    
    UIImage *currentImage = self.imageView.image;
    NSUInteger index = [self.images indexOfObject:currentImage];
    index = (index + 1) % self.images.count;
    self.imageView.image = self.images[index];
}
7.CASpringAnimation弹簧动画

CASpringAnimation弹簧动画,带有初始速度以及阻尼指数等物理参数的属性动画。

  • mass -> 质量越大,弹簧拉伸和压缩的幅度越大,动画的速度变慢,并且波动幅度变大,影响图层运动时的弹簧惯性
  • stiffness -> 弹簧的劲度系数。刚度系数越大,形变产生的力就越大,运动越快
  • damping -> 阻尼系数,地面的摩擦力。阻尼系数越大,停止越快
  • initialVelocity -> 初始速度,相当于给小球一个初始速度(可正可负,方向不同),初始速率,动画视图的初始速度大小
    速率为正数时,速度方向与运动方向一致,速率为负数时,速度方向与运动方向相反
  • settlingDuration -> 结算时间 返回弹簧动画到停止时的估算时间,根据当前的动画参数估算 通常弹簧动画的时间使用结算时间比较准确
    self.animationView = [[UIView alloc]init];
    self.animationView.frame = CGRectMake(0, kHeight/2-50, 50, 50);
    self.animationView.backgroundColor = [UIColor greenColor];
    [self.view addSubview:self.animationView];
    
    //弹簧效果
    CASpringAnimation *spring  = [CASpringAnimation animationWithKeyPath:@"position.y"];
    spring.fromValue = @150;
    spring.toValue = @100;
    //阻尼系数
    spring.damping = 0.1;
    //刚度系数: (劲度系数 / 弹性系数): 系数越大,形变的产生的力越大, 运动越快
    spring.stiffness = 10;
    //质量: 影响图层运动时候的惯性, 质量越大弹簧拉伸和压缩的幅度越大 (动画的幅度,波动变大)
    spring.mass = 1;
    //初识速率: 动画视图的初识速度大小
    //速率为正时候, 速度方向与运动方向一致, 否则相仿.
    spring.initialVelocity = 1;
    // settlingDuration 结算时间,预估弹簧动画到停住的时间的估算, 根据当前动画的各个参数估算, 通常弹簧动画的估算时间使用结算时间比较准确
    spring.duration = spring.settlingDuration;
    [self.animationView.layer addAnimation:spring forKey:@"springAnimation"];

动画demo

七、核心动画KeyPath表

  • 1.CALayer
keyPath 描述
transform.rotation.x 按x轴旋转的弧度
transform.rotation.y 按y轴旋转的弧度
transform.rotation.z 按z轴旋转的弧度
transform.scale 按比例放大缩小
transform.scale.x 在x轴按比例放大缩小
transform.scale.y 在y轴按比例放大缩小
transform.scale.z 在z轴按比例放大缩小
transform.translation x,y 坐标均发生改变
transform.translation.x 沿x轴平移
transform.translation.y 沿y轴平移
transform.translation.z 沿z轴平移
transform CATransform3D 4*4矩阵
bounds layer大小
frame layer位置/大小
position layer位置
anchorPoint 锚点位置
cornerRadius 圆角大小
zPosition z轴位置
sublayers 子layers
sublayerTransform 子layers的CATransform3D 4*4矩阵
filters 滤镜
backgroundColor 背景颜色
backgroundFilters 背景滤镜
contents Layer内容,呈现在背景颜色之上
contentsRect Layer内容的Rect
path 路径
mask 遮罩蒙版
masksToBounds 是否显示超出边缘部分
doubleSided 是否双面都渲染
borderColor 描边颜色
borderWidth 描边宽度
shadowColor 阴影颜色
shadowOffset 阴影偏移距离
shadowOpacity 阴影透明度
shadowRadius 阴影圆角
shadowPath 阴影路径
opacity 透明度
hidden 是否隐藏
  • 2.CAGradientLayer
keyPath 描述
colors 颜色渐变
locations 渐变位置
startPoint 开始点
endPoint 终止点
  • 3.CAShapeLayer
keyPath 描述
fillColor 填充颜色
strokeStart 边框颜色开始,从无到有
strokeEnd 边框颜色结束,从有到无
strokeColor 路径颜色
lineWidth 路径的线宽
miterLimit 相交长度的最大值
lineDashPhase 虚线样式
  • 4.CAEmitterLayer
keyPath 描述
emitterPosition 粒子发射器位置
emitterZPosition 粒子发射器Z深度
emitterSize 粒子发射器大小
  • 5.CAReplicatorLayer
keyPath 描述
instanceDelay -
instanceTransform -
instanceRedOffset -
instanceGreenOffset -
instanceBlueOffset -
instanceAlphaOffset -
  • 6.CATextLayer
keyPath 描述
fontSize 字体大小
foregroundColor 背景颜色
  • 7.CATransform3D
keyPath 描述
rotation.x -
rotation.y -
rotation.z -
rotation -
scale.x -
scale.y -
scale.z -
scale -
translation.x -
translation.y -
translation.z -
  • 8.CGPoint
keyPath 描述
x -
y -
  • 9.CGSize
keyPath 描述
width -
height -
  • 10.CGRect
keyPath 描述
origin -
origin.x -
origin.y -
size -
size.width -
size.height -
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。