随笔《Clione的电灯的光》整顿电视动漫,二零一七年十二月开始播放!动漫宗旨曲由aki担当演唱,别的还会有一张宣传图公开。其余音讯暂未公布。

在上一篇中大家讨论了layer的隐式动漫,隐式动漫是四个很棒的兑现layer层基本功动漫的法子,不过它并不能落到实处layer层的首要性帧动漫和接通动漫,所以本篇将学习layer的显式动画,显式动漫可分为:属性动漫(功底动漫和首要性帧动漫)、动画组连片动漫

其次篇隐式动漫我们聊起隐式动漫可以直接成效于layer的可动画属性,可是不能够从来效果于UIView关联的不胜layer的可动漫属性,因为UI基特框架把UIView关联的layer的隐式动漫给禁止使用了。而显式动漫就不均等了,显式动漫也是效果与利益于layer层的,可是它不仅能够功能于直接开立的layer,也得以成效于view关联的layer,所以大家就不用区分了,直接怼layer就足以了。


目录

一、属性动漫(CAPropertyAnimation)

1、基本功动漫(CABasicAnimation)
(1)什么是底工动漫?
(2)怎么着行使根基动漫?
(3)例如表达幼功动漫必要注意的多个地方及减轻
2、关键帧动漫(CAKeyframeAnimation)
(1)什么是首要帧动画?
(2)怎么着行使主要帧动漫?
(3)举例表明设置关键帧的五个措施:数组关键帧法和渠道关键帧法

二、动画组(CAAnimationGroup)

(1)什么是动漫组?
(2)怎么样利用动漫组?

三、过渡动漫

(1)什么是对接动漫?
(2)如何行使过渡动漫?

四、什么情状下使用突显动画


一、属性动漫(CAPropertyAnimation)

我们清楚想要做属性动漫的话,能够直接行使UIView的block属性动漫,也足以动用layer的隐式动漫来落到实处,那么这里的layer展现动漫的习性动漫正是我们落到实处属性动漫的第三种选拔。

属性动漫又有八个子类,大家通常首要选拔那多个子类来做动漫,它们是底工动漫(CABasicAnimation)表里一致帧动漫(CAKeyframeAnimation),接下去大家将各自介绍:

1、功底动漫(CABasicAnimation)
(1)什么是功底动漫?

首先篇中UIView block底子动漫说过了,相符。

(2)怎样选择底工动漫?

功底动漫的行使也异常粗略,只需求按以下7个步骤来就能够了:

  • 成立贰个功底动漫
  • 安装好根基动漫的代理(回调中要干活的)
  • 钦定底子动漫要改成的性格
  • 给功底动漫一个开端值(不给也行,会默感觉layer伊始状态对应属性的值)
  • 给基本功动漫一个得了值
  • 再钦赐一些底子动漫的任何设置(如动漫时间长度、重复次数等)
  • 然后把那么些底工动漫增加到layer上,动漫就能够起来履行了
(3)举例

给customLayer背景观的改变加二个动漫片,给customLayer1切圆角的变动加二个动漫片

(清单3.1)

//
//  ViewController.m
//  CoreAnimation
//
//  Created by 意一yiyi on 2017/11/13.
//  Copyright © 2017年 意一yiyi. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()<CAAnimationDelegate>

@property (strong, nonatomic) CALayer *customLayer;
@property (strong, nonatomic) CALayer *customLayer1;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.customLayer = [[CALayer alloc] init];
    self.customLayer.frame = CGRectMake(100, 100, 100, 100);
    self.customLayer.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:self.customLayer];

    self.customLayer1 = [[CALayer alloc] init];
    self.customLayer1.frame = CGRectMake(100, 250, 100, 100);
    self.customLayer1.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:self.customLayer1];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    CABasicAnimation *basicAnimation = [[CABasicAnimation alloc] init];
    NSLog(@"customLayer背景色basicAnimation===%@", basicAnimation);
    basicAnimation.delegate = self;
    basicAnimation.keyPath = @"backgroundColor";
    basicAnimation.toValue = (__bridge id _Nullable)([UIColor orangeColor].CGColor));
    basicAnimation.duration = 3;
    [self.customLayer addAnimation:basicAnimation forKey:nil];

    CABasicAnimation *basicAnimation1 = [[CABasicAnimation alloc] init];
    NSLog(@"customLayer1切圆角basicAnimation1===%@", basicAnimation1);
    basicAnimation1.delegate = self;
    basicAnimation1.keyPath = @"cornerRadius";
    basicAnimation1.toValue = @(50);
    basicAnimation1.duration = 3;
    [self.customLayer1 addAnimation:basicAnimation1 forKey:nil];
}

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

    NSLog(@"动画开始了===%@", anim);
}

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

    NSLog(@"动画结束了===%@", anim);
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

图片 1

1.gif

运营,大家得以见到真的有了动漫,然则也意识了如下难题:

  • 卡通在做到之后又跳回到伊始状态了,那是为何?
    • 本着那几个难点:其实底工动漫只是设想出来的视觉效果,并不曾真正转移layer做动漫那几个属性的值,所以大家要在动画结束把layer做动漫的格外属性的值改善为动漫片的结束值。同期咱们要注意在动漫甘休重新初始化layer属性值的时候,要记得关闭layer的隐式动漫,不然既会有底子动漫带给的卡通也有隐式动漫带给的卡通,就重叠了。校正动漫甘休的代办方法如下:

(清单3.2)

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

    NSLog(@"动画结束了===%@", anim);

    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    self.customLayer.backgroundColor = [UIColor orangeColor].CGColor;
    self.customLayer1.cornerRadius = 50;
    [CATransaction commit];
}

图片 2

1.gif

运维,开采能够了,不过又开掘八个难题:

  • 转移layer属性值的时候,layer飞速地闪回到初阶状态才成为截止值,那是为啥?(模拟器是还不荒谬的,所以调节和测量检验动漫必定要在真机上整)

    • 本着这一个标题:我们供给在动漫甘休以往,设置layer保持哪一帧,须要设置为涵养动漫结束后的那一帧,何况以前设置动画甘休后不活动移除,而是在急需的时候手动移除。通过那五个属性的安装(即animationremovedOnCompletionfillMode七个属性),动漫在终结时就不会火速闪回伊始状态再产生截止状态了,代码如下:

(清单3.3)

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    CABasicAnimation *basicAnimation = [[CABasicAnimation alloc] init];
    NSLog(@"customLayer背景色basicAnimation===%@", basicAnimation);
    basicAnimation.delegate = self;
    basicAnimation.keyPath = @"backgroundColor";
    basicAnimation.toValue = (__bridge id _Nullable)([UIColor orangeColor].CGColor);
    basicAnimation.duration = 3;
    basicAnimation.removedOnCompletion = NO;// 动画结束后不自动移除动画
    basicAnimation.fillMode = kCAFillModeForwards;// 动画结束后保持结束时的那一帧
    [self.customLayer addAnimation:basicAnimation forKey:nil];

    CABasicAnimation *basicAnimation1 = [[CABasicAnimation alloc] init];
    NSLog(@"customLayer1切圆角basicAnimation1===%@", basicAnimation1);
    basicAnimation1.delegate = self;
    basicAnimation1.keyPath = @"cornerRadius";
    basicAnimation1.toValue = @(50);
    basicAnimation1.duration = 3;
    basicAnimation1.removedOnCompletion = NO;
    basicAnimation1.fillMode = kCAFillModeForwards;
    [self.customLayer1 addAnimation:basicAnimation1 forKey:nil];
}
  • 再有多少个难点不怕,只要我们在三个调整器里面创制了多个卡通的话(比方(项目清单3.1)中我们独家给customLayer和customLayer1创制了三个卡通),那么那八个卡通都会走到同几个动漫甘休的代理方法里,我们想要达到的动漫指标是customLayer的卡通片停止时改造customLayer的背景观,customLayer1的卡通片停止时退换customLayer1的圆角,实际不是(清单3.1)中这种把customLayer和customLayer1两个同期校订,那如何是好吧?有两种艺术,我们分别看一下:

    • 办法一:我们看出动漫结束的代办方法是有个参数anim把动漫带回来的,那是或不是我们得以把大家成立的动漫创设成属性,来那边比对,对上号之后改正相应layer的习性不就可以了呗。看似非常轻巧完美的艺术。不过你也看到我们有打字与印刷操作了,看下调控台的输出吧:

(清单3.3)

2018-01-16 11:06:09.205151+0800 CoreAnimation[1582:390479] customLayer背景色basicAnimation===<CABasicAnimation: 0x1c803aa40>
2018-01-16 11:06:09.205444+0800 CoreAnimation[1582:390479] customLayer1切圆角basicAnimation1===<CABasicAnimation: 0x1c803ab20>
2018-01-16 11:06:09.205989+0800 CoreAnimation[1582:390479] 动画开始了===<CABasicAnimation: 0x1c803ab40>
2018-01-16 11:06:09.206101+0800 CoreAnimation[1582:390479] 动画开始了===<CABasicAnimation: 0x1c803ab00>
2018-01-16 11:06:12.207372+0800 CoreAnimation[1582:390479] 动画结束了===<CABasicAnimation: 0x1c803ab40>
2018-01-16 11:06:12.207838+0800 CoreAnimation[1582:390479] 动画结束了===<CABasicAnimation: 0x1c803ab00>

大家欣喜地窥见,我们创设的根底动画和动漫初叶、甘休代理方法带回去的卡通片并非叁个动漫。因为动漫开端、甘休代理方法带回来的动画片是大家创立的根基动漫的深拷贝,omg,这种艺术失败了。

  • 办法二:回到(清单3.1)可以见见,大家在给layer增添动漫的秘诀-addAnimation: forKey:的key大家给的是空,其实我们能够在此个地点给animation关联贰个key,这么些key其实正是我们能博取到内定animation的独一标志。我们修改代码如下:

(清单3.4)

//
//  ViewController.m
//  CoreAnimation
//
//  Created by 意一yiyi on 2017/11/13.
//  Copyright © 2017年 意一yiyi. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()<CAAnimationDelegate>

@property (strong, nonatomic) CALayer *customLayer;
@property (strong, nonatomic) CALayer *customLayer1;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.customLayer = [[CALayer alloc] init];
    self.customLayer.frame = CGRectMake(100, 100, 100, 100);
    self.customLayer.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:self.customLayer];

    self.customLayer1 = [[CALayer alloc] init];
    self.customLayer1.frame = CGRectMake(100, 250, 100, 100);
    self.customLayer1.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:self.customLayer1];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    CABasicAnimation *basicAnimation = [[CABasicAnimation alloc] init];
    NSLog(@"customLayer背景色basicAnimation===%@", basicAnimation);
    basicAnimation.delegate = self;
    basicAnimation.keyPath = @"backgroundColor";
    basicAnimation.toValue = (__bridge id _Nullable)([UIColor orangeColor].CGColor);
    basicAnimation.duration = 3;
    [self.customLayer addAnimation:basicAnimation forKey:@"basicAnimation"];

    CABasicAnimation *basicAnimation1 = [[CABasicAnimation alloc] init];
    NSLog(@"customLayer1切圆角basicAnimation1===%@", basicAnimation1);
    basicAnimation1.delegate = self;
    basicAnimation1.keyPath = @"cornerRadius";
    basicAnimation1.toValue = @(50);
    basicAnimation1.duration = 3;
    [self.customLayer1 addAnimation:basicAnimation1 forKey:@"basicAnimation1"];
}

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

    NSLog(@"动画开始了===%@", anim);
}

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

    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    self.customLayer.backgroundColor = [UIColor orangeColor].CGColor;
    self.customLayer1.cornerRadius = 50;
    [CATransaction commit];

    NSLog(@"动画结束了===%@, %@", [self.customLayer animationForKey:@"basicAnimation"], self.customLayer1.animationKeys);
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

可是运转,发掘输出都以空,不理解为啥?待解。

(清单3.5)

2018-01-16 13:12:46.985628+0800 CoreAnimation[1695:434274] customLayer背景色basicAnimation===<CABasicAnimation: 0x1c803e280>
2018-01-16 13:12:46.986083+0800 CoreAnimation[1695:434274] customLayer1切圆角basicAnimation1===<CABasicAnimation: 0x1c803e360>
2018-01-16 13:12:46.986961+0800 CoreAnimation[1695:434274] 动画开始了===<CABasicAnimation: 0x1c803e380>
2018-01-16 13:12:46.987066+0800 CoreAnimation[1695:434274] 动画开始了===<CABasicAnimation: 0x1c803e340>
2018-01-16 13:12:49.988287+0800 CoreAnimation[1695:434274] 动画结束了===(null), (null)
2018-01-16 13:12:49.988567+0800 CoreAnimation[1695:434274] 动画结束了===(null), (null)
  • 措施三:幸运的是,大家还应该有第三种艺术。正是Core
    Animation完成了KVC,所以能够随意给多少个动漫贴标签,何况key和value都是id类型的
    ,所以这里大家就足以吧layer作为value给底蕴动漫贴个标签,然后再动漫甘休的回调里就能够料定出切实是哪个动漫甘休了。校订代码如下:

(清单3.6)

//
//  ViewController.m
//  CoreAnimation
//
//  Created by 意一yiyi on 2017/11/13.
//  Copyright © 2017年 意一yiyi. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()<CAAnimationDelegate>

@property (strong, nonatomic) CALayer *customLayer;
@property (strong, nonatomic) CALayer *customLayer1;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.customLayer = [[CALayer alloc] init];
    self.customLayer.frame = CGRectMake(100, 100, 100, 100);
    self.customLayer.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:self.customLayer];

    self.customLayer1 = [[CALayer alloc] init];
    self.customLayer1.frame = CGRectMake(100, 250, 100, 100);
    self.customLayer1.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:self.customLayer1];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    CABasicAnimation *basicAnimation = [[CABasicAnimation alloc] init];
    NSLog(@"customLayer背景色basicAnimation===%@", basicAnimation);
    basicAnimation.delegate = self;
    basicAnimation.keyPath = @"backgroundColor";
    basicAnimation.toValue = (__bridge id _Nullable)([UIColor orangeColor].CGColor);
    basicAnimation.duration = 3;
    [basicAnimation setValue:self.customLayer forKey:@"tag"];
    [self.customLayer addAnimation:basicAnimation forKey:nil];

    CABasicAnimation *basicAnimation1 = [[CABasicAnimation alloc] init];
    NSLog(@"customLayer1切圆角basicAnimation1===%@", basicAnimation1);
    basicAnimation1.delegate = self;
    basicAnimation1.keyPath = @"cornerRadius";
    basicAnimation1.toValue = @(50);
    basicAnimation1.duration = 3;
    [basicAnimation1 setValue:self.customLayer1 forKey:@"tag"];
    [self.customLayer1 addAnimation:basicAnimation1 forKey:nil];
}

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

    NSLog(@"动画开始了===%@", anim);
}

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

    if ([anim valueForKey:@"tag"] == self.customLayer) {

        [CATransaction begin];
        [CATransaction setDisableActions:YES];
        self.customLayer.backgroundColor = [UIColor orangeColor].CGColor;
        [CATransaction commit];
    }

    if ([anim valueForKey:@"tag"] == self.customLayer1) {

        [CATransaction begin];
        [CATransaction setDisableActions:YES];
        self.customLayer1.cornerRadius = 50;
        [CATransaction commit];
    }

    NSLog(@"动画结束了===%@, %@", [self.customLayer animationForKey:@"basicAnimation"], self.customLayer1.animationKeys);
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
2、关键帧动漫(CAKeyframeAnimation)
(1)什么是任重(Ren Zhong)而道远帧动漫?

器重帧动漫同样也是性质动漫的四个子类,它也是用来做layer层的性子动漫的,它能够用来做一些比较复杂的属性动漫。比方说,大家来看底蕴动漫的叁个缺陷就是它只必要给四个开端值和了结值就能够了,那样的效应在水田下就展现生硬以至无法知足供给。而关键帧动画就可以补助大家超脱根基动漫仅仅是开始值和甘休值的牢笼,能够专擅安装三翻五遍串关键帧,以至是绘制曲线。

(2)怎么样使用首要帧动漫?

首要帧动漫的使用也异常的粗略,只须求按以下7个步骤来就能够了:

  • 成立叁个要害帧动漫
  • 安装好根本帧动漫的代办(回调中要干活的)
  • 钦命关键帧动漫要转移的属性
  • 给关键帧动漫的values属性设置一写关键帧(注意第一帧无法大致,它不会默感到layer初阶状态的属性值,第一帧大家要积极设置为layer伊始状态的属性值,不然会从开头状态的值直接跳变到第一帧)的数组大概路线绘制设置重大帧法
  • 再钦赐一些幼功动漫的别样设置(如动漫时间长度、重复次数等)
  • 下一场把这几个根基动漫增添到layer上,动漫就能够起来举行了
(3)例如
  • values数组关键帧法:校订customLayer的背景观
    (清单3.7)

//
//  ViewController.m
//  CoreAnimation
//
//  Created by 意一yiyi on 2017/11/13.
//  Copyright © 2017年 意一yiyi. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()<CAAnimationDelegate>

@property (strong, nonatomic) CALayer *customLayer;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.customLayer = [[CALayer alloc] init];
    self.customLayer.frame = CGRectMake(100, 100, 100, 100);
    self.customLayer.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:self.customLayer];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    CAKeyframeAnimation *basicAnimation = [[CAKeyframeAnimation alloc] init];
    basicAnimation.delegate = self;
    basicAnimation.keyPath = @"backgroundColor";
    basicAnimation.values = @[
                              (__bridge id _Nullable)([UIColor redColor].CGColor),// 第一帧我们要主动设置为layer初始状态的属性值
                              (__bridge id _Nullable)([UIColor orangeColor].CGColor),
                              (__bridge id _Nullable)([UIColor yellowColor].CGColor),
                              (__bridge id _Nullable)([UIColor greenColor].CGColor)
                              ];
    basicAnimation.duration = 3;
    [basicAnimation setValue:self.customLayer forKey:@"tag"];
    [self.customLayer addAnimation:basicAnimation forKey:nil];
}

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

    NSLog(@"动画开始了");
}

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

    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    self.customLayer.backgroundColor = [UIColor greenColor].CGColor;
    [CATransaction commit];

    NSLog(@"动画结束了");
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

图片 3

1.gif

  • 路径关键帧法:让layer沿一个一回贝塞尔曲线移动

大家知晓UIView
block关键帧动漫只可以设置数组关键帧,所以若是有的场景下,大家供给连接的关键帧就必要接纳显式动漫的第一帧动漫了,它扶助路线关键帧。

(清单3.8)

//
//  ViewController.m
//  CoreAnimation
//
//  Created by 意一yiyi on 2017/11/13.
//  Copyright © 2017年 意一yiyi. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()<CAAnimationDelegate>

@property (strong, nonatomic) UIImageView *customImageView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.customImageView = [[UIImageView alloc] init];
    self.customImageView.frame = CGRectMake(100, 100, 100, 100);
    self.customImageView.backgroundColor = [UIColor clearColor];
    self.customImageView.image = [UIImage imageNamed:@"汽车"];
    [self.view addSubview:self.customImageView];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    CAKeyframeAnimation *keyframeAnimation = [[CAKeyframeAnimation alloc] init];
    keyframeAnimation.delegate = self;
    keyframeAnimation.keyPath = @"position";

    // 绘制一个三次贝塞尔曲线
    UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
    [bezierPath moveToPoint:CGPointMake(150, 150)];
    [bezierPath addCurveToPoint:CGPointMake(150, 450) controlPoint1:CGPointMake(250, 250) controlPoint2:CGPointMake(50, 350)];
    // 绘制一个shapeLayer放在屏幕上显得更形象
    CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
    shapeLayer.path = bezierPath.CGPath;
    shapeLayer.fillColor = [UIColor clearColor].CGColor;
    shapeLayer.strokeColor = [UIColor magentaColor].CGColor;
    shapeLayer.lineWidth = 3.0f;
    [self.view.layer addSublayer:shapeLayer];

    keyframeAnimation.path = bezierPath.CGPath;
    keyframeAnimation.duration = 3;
    keyframeAnimation.rotationMode = kCAAnimationRotateAuto;// 让layer根据曲线的切线自动旋转方向
    [keyframeAnimation setValue:self.customImageView forKey:@"tag"];
    [self.customImageView.layer addAnimation:keyframeAnimation forKey:nil];
}

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

    NSLog(@"动画开始了");
}

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

    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    self.customImageView.layer.position = CGPointMake(150, 450);
    [CATransaction commit];

    NSLog(@"动画结束了");
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

图片 4

1.gif

二、动画组

(1)什么是动漫组?

卡通组其实很粗大略了,它是其它二个接续于CAAnimation的子类,它提供了二个animations的数组属性用来把过多少个默转潜移感动漫组成起来协同施行和决定,防止一群动漫单个调控的累赘

当然了,我们绝不组合卡通而是把单个单个的卡通分别添在同二个layer上也是能够的。

(2)怎么样行使动漫组?

一点也不细略了,创设单个单个的动漫片,然后把那个单个单个的动漫片赋值给动漫组的animations数组,然后把那几个动漫组加多到layer上,这一群动漫就能够起先还要实践了。

举个例子:把上边的底蕴动漫和重大帧动漫组成起来,构成动漫组。
(清单3.9)

//
//  ViewController.m
//  CoreAnimation
//
//  Created by 意一yiyi on 2017/11/13.
//  Copyright © 2017年 意一yiyi. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()<CAAnimationDelegate>

@property (strong, nonatomic) CALayer *customLayer;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.customLayer = [[CALayer alloc] init];
    self.customLayer.frame = CGRectMake(100, 100, 100, 100);
    self.customLayer.backgroundColor = [UIColor redColor].CGColor;
    self.customLayer.contents = (__bridge id _Nullable)([UIImage imageNamed:@"汽车"].CGImage);
    self.customLayer.contentsScale = [UIScreen mainScreen].scale;
    [self.view.layer addSublayer:self.customLayer];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    // 基础动画
    CABasicAnimation *basicAnimation = [[CABasicAnimation alloc] init];
    basicAnimation.keyPath = @"backgroundColor";
    basicAnimation.toValue = (__bridge id _Nullable)([UIColor orangeColor].CGColor);

    // 关键帧动画
    CAKeyframeAnimation *keyframeAnimation = [[CAKeyframeAnimation alloc] init];
    keyframeAnimation.keyPath = @"position";
    // 绘制一个三次贝塞尔曲线
    UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
    [bezierPath moveToPoint:CGPointMake(150, 150)];
    [bezierPath addCurveToPoint:CGPointMake(150, 450) controlPoint1:CGPointMake(250, 250) controlPoint2:CGPointMake(50, 350)];
    // 绘制一个shapeLayer放在屏幕上显得更形象
    CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
    shapeLayer.path = bezierPath.CGPath;
    shapeLayer.fillColor = [UIColor clearColor].CGColor;
    shapeLayer.strokeColor = [UIColor magentaColor].CGColor;
    shapeLayer.lineWidth = 3.0f;
    [self.view.layer addSublayer:shapeLayer];
    keyframeAnimation.path = bezierPath.CGPath;
    keyframeAnimation.rotationMode = kCAAnimationRotateAuto;// 让layer根据曲线的切线自动旋转方向

    // 动画组
    CAAnimationGroup *animationGroup = [[CAAnimationGroup alloc] init];
    animationGroup.delegate = self;
    animationGroup.animations = @[basicAnimation, keyframeAnimation];
    animationGroup.duration = 3;
    [self.customLayer addAnimation:animationGroup forKey:nil];
}

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

    NSLog(@"动画开始了");
}

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

    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    self.customLayer.backgroundColor = [UIColor orangeColor].CGColor;
    self.customLayer.position = CGPointMake(150, 450);
    [CATransaction commit];

    NSLog(@"动画结束了");
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

图片 5

1.gif

三、过渡动漫

(1)什么是连接动漫?

先是篇说过了,相似。

连片动漫(CATransition)同样是CAAnimation的叁个子类,但它不像属性动漫那样是平缓地在多少个属性值之间做动漫,而是直白对全部图层做变通(即过渡动漫不是照准图层的习性的,而是针对图层的,当然它能够用来做属性动漫而不囿于于做属性动漫,大家竟然可以在不改动图层只怕不知底改造了图层什么东西的事态下间接给图层加多贰个联网动画,相当于说过渡动漫是给图层添的卡通片,只要有layer存在,大家别的时机任何情状都能给layer增多衔接动漫,能够给layer添,也得以给view关联的layer添),即第一呈现改正前的图层外观,然后经过三个接通动漫的功力转换成新的外参观展览示

(2)怎么样行使过渡动漫?
  • 创建过渡动漫
  • 安装好过渡动漫的代理
  • 设置过渡动漫类型, 过渡动漫子类型, 过渡动漫卡通速度及别的一些装置
  • 安装图层的新外观
  • 把过渡动漫增多到layer上,过渡动画就最早推行了

接通动漫类型(type):用来支配过渡动漫的效应,有上面九种:

fade// 淡入淡出的效果(没有方向)
push// 新图层从一侧推入、旧图层从一侧推出来展示新外观效果
moveIn// 新图层从一侧推入来展示新外观效果、但旧图层没有从一侧推出
reveal// 旧图层从一侧推出来展示新外观效果、但新图层没有从一侧推入
oglFlip// 正面和背面的二维翻转效果
cube// 立方体翻转效果
pageCurl// 翻页效果
suckEffect// 收缩效果
rippleEffect// 水滴波纹效果(没有方向)

连片动漫子类型如下(subType):用来调整过渡动漫的自由化,有下边二种,type里除了fade和rippleEffect没有动向之外,其余功用都有方向

kCATransitionFromTop// 从底部开始过渡动画
kCATransitionFromLeft// 从左侧开始过渡动画
kCATransitionFromBottom// 从顶部开始过渡动画
kCATransitionFromRight// 从右侧开始过渡动画

转场动漫缓冲曲线调整(timingFunction):有上面各类

kCAMediaTimingFunctionEaseInEaseOut// 动画慢进,逐渐加快,逐渐减慢,慢出
kCAMediaTimingFunctionEaseIn// 动画慢进,逐渐加快
kCAMediaTimingFunctionEaseOut// 动画逐渐减慢,慢出
kCAMediaTimingFunctionLinear// 动画匀速

可以预知layer显式动漫的连通动漫效果要比UIView
block过渡动漫的成效多了广大,由此效果也会更充分一些。

下边举个例子,雷同第一篇的,切换imageView的图纸和label的公文,只不过是个水纹效果:

//
//  ViewController.m
//  CoreAnimation
//
//  Created by 意一yiyi on 2017/11/13.
//  Copyright © 2017年 意一yiyi. All rights reserved.
//

#import "ViewController.h"

#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height

@interface ViewController ()<CAAnimationDelegate>

@property (strong, nonatomic) UIImageView *customImageView;
@property (strong, nonatomic) UILabel *label;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.customImageView = [[UIImageView alloc] init];
    self.customImageView.frame = CGRectMake(0, 64, kScreenWidth, kScreenWidth);
    self.customImageView.backgroundColor = [UIColor redColor];
    self.customImageView.image = [UIImage imageNamed:@"0.jpg"];
    [self.view addSubview:self.customImageView];

    self.label = [[UILabel alloc] init];
    self.label.frame = CGRectMake(0, kScreenWidth + 100, kScreenWidth, 30);
    self.label.text = @"奥黛丽·赫本";
    self.label.textColor = [UIColor blackColor];
    self.label.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:self.label];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    // 创建过渡动画
    CATransition *transition = [[CATransition alloc] init];

    // 设置好过渡动画的代理
    transition.delegate = self;

    // 设置过渡动画类型、子类型、时间曲线及其它一些设置
    transition.type = @"rippleEffect";
    transition.subtype = kCATransitionFromTop;
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.duration = 3;

    // 设置图层的新外观
    NSInteger num = arc4random()%7;
    self.customImageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%ld.jpg", num]];
    switch (num) {
        case 0:
            self.label.text = @"奥黛丽·赫本";
            break;
        case 1:
            self.label.text = @"苏菲·玛索";
            break;
        case 2:
            self.label.text = @"泰勒·斯威夫特";
            break;
        case 3:
            self.label.text = @"安妮·海瑟薇";
            break;
        case 4:
            self.label.text = @"娜塔丽·波特曼";
            break;
        case 5:
            self.label.text = @"凯拉·奈特利";
            break;
        case 6:
            self.label.text = @"杰西卡·阿尔芭";
            break;
    }

    // 把过渡动画添加到layer上
    [self.customImageView.layer addAnimation:transition forKey:nil];
    [self.label.layer addAnimation:transition forKey:nil];
}

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

    NSLog(@"动画开始了");
}

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

    NSLog(@"动画结束了");
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

图片 6

1.gif

四、什么状态下接受呈现动漫

本着根底动漫:用UIView
block底蕴动漫和layer的隐式动漫就够了,layer的显式动漫的底蕴动漫也没多吗,用起来反而累赘。

针对重大帧动漫:日常情状下选取UIView
block关键帧动漫就能够,不过倘假设索要连接关键帧的气象就需求接受layer的显式动画的最主要帧动画。

针对过渡动漫:平时景色下选用UIView
block过渡动画就能够,但是只假使内需更增进动漫效果的现象能够应用layer的显式动漫的连结动漫。

如上所述,大家一时还尚无须要直接开立layer来做动漫,开拓中符合规律用UIView就可以了,UIView
block动漫就不说了,隐式动漫和显示动漫也都以足以直接或直接地效用于view关联的layer的。

相关文章