iOS篇-UI篇-CoreAnimation(核心动画)

TZ : 飞机虽然飞的很快,但是我们不要忘了思考

一 : 科普一分钟

我们看到很多产品都有炫酷的动画,我们会有跃跃欲试的感觉,复杂的结构拆解开各个小部分,都是有基本的动画效果组合而成,下面主要介绍一下CoreAnimation这套苹果为我们提供的功能强大的api,为我们提供了各种动画效果.配合着我们的想象力来实现各种效果.

二 : CALayer和其重要属性

CALayer 我们平时的基础控件包含UIview, 点击按钮,label,等等.这些控件之所以能显示在我们的眼前,因为这些控件上都有一个图层 CALayer

我们在创建这些基础控件时,其内部会自动创建一个图层 CALayer对象.

  1. 给UIView CALayer属性约束
@property (strong, nonatomic) IBOutlet UIView *tzView;

  //设置阴影的颜色
    self.tzView.layer.shadowColor = [UIColor orangeColor].CGColor;
    
     //设置阴影的不透明度
    self.tzView.layer.shadowOpacity = 1;
    
    self.tzView.layer.shadowOffset = CGSizeMake(-5, -5);
    
    //设置阴影模糊半径
    self.tzView.layer.shadowRadius = 5;
    
    //边框宽度,往里边延伸
    self.tzView.layer.borderWidth = 2;
    self.tzView.layer.borderColor = [UIColor greenColor].CGColor;
    
    //设置圆角
    
    self.tzView.layer.cornerRadius = 50;

  1. 给UIImageView CALayer属性约束
@property (strong, nonatomic) IBOutlet UIImageView *tzImageView;

//设置阴影的颜色
    self.tzImageView.layer.shadowColor = [UIColor orangeColor].CGColor;
    
    //设置阴影的不透明度
    self.tzImageView.layer.shadowOpacity = 1;
    
    self.tzImageView.layer.shadowOffset = CGSizeMake(-5, -5);
    
    //设置阴影模糊半径
    self.tzImageView.layer.shadowRadius = 5;
    
    //边框宽度,往里边延伸
    self.tzImageView.layer.borderWidth = 2;
    self.tzImageView.layer.borderColor = [UIColor greenColor].CGColor;
    
    //设置圆角
    
    self.tzImageView.layer.cornerRadius = 50;
    
    //把超过根层以外的东西都剪裁掉.
    self.tzImageView.layer.masksToBounds = YES;

对于 imageView 我们设置圆角的时候 要 加一行代码 self.tzImageView.layer.masksToBounds = YES;

这个是因为 imageView 的 layer 层 上面还有一层 contens来存放 图片 如果不加上述代码,只是对其根层设置圆角,并没有对 contens 设置

  1. 我们自己写一个 CALayer
CALayer *layer = [CALayer layer];
        layer.backgroundColor = [UIColor redColor].CGColor;
        layer.frame = CGRectMake(50, 50, 100, 100);
    [self.view.layer addSublayer:layer];
    
    layer.contents = (id)[UIImage imageNamed:@"tz.jpg"].CGImage;

注意 : CAlayer 是定义在 QuartzCore框架的
CGImagerRef CGColorRef是定义在CoreGraphics
UIImageUIColor 是定义在UIKit框架中的
QuartzCoreCoreGraphics 框架是可以跨平台的在MacOSX 和 iOS 上都可以使用
为了保证移植性 QuartzCore不能使用 UIImage
UIColor 只能使用 CGImagerRefCGColorRef
所以我们通常会转一下

  1. CATransform3D

    我们想改变图层的形变平移等等动画是怎么做的呢,可以用这个

@property (strong, nonatomic) IBOutlet UIImageView *imageView;

参数 1 : 运动角度
参数 2 : 在 X 轴 上是否有运动,
参数 3 : 在 Y轴上是否有运动
参数 4 : 在 Z轴上是否有运动

      self.imageView.layer.transform = CATransform3DMakeRotation(M_PI, 1, 1, 0);

快速写法

 [self.imageView.layer setValue:@(100) forKeyPath:@"transform.translation.x"];
  1. positionanchorPoint 属性

CALayer 特别重要的两个属性

position : 用来设置 CAlayer在父层中的位置 以父层左上角为原点(0,0)

anchorPoint : 又称为 锚点决定了CALayer身上 的哪个点会在 position所指定的位置, 以自己的左上角为原点(0,0) X, 和 Y的 取值范围 0~1
默认值为 (0.5,0.5);

图解 .jpg

我们把 锚点也就是 anchorPoint 点 想象成 CALayer上的一个钉子,把父层想象成一面墙 上面有个洞 就是 position 现在那个洞在哪个地方 我们就用钉子 扎到哪个地方,这个是不是好理解了一点. 接下来用代码 来描述

@property(nonatomic,weak)CALayer *layer;

   CALayer *layer = [CALayer layer];
    layer.frame = CGRectMake(200, 200, 100, 100);
    layer.backgroundColor = [UIColor greenColor].CGColor;
  
    self.layer = layer;
    
    [self.view.layer addSublayer:layer];

接下来我们让它 进行改变 看看效果

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
  self.layer.anchorPoint = CGPointMake(0, 0);            

  self.layer.position = CGPointMake(0,0);

}
效果.gif

假如我们没有设置 anchorPoint 会有什么效果呢 别忘了默认是 (0.5,0.5)哦

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    
       self.layer.position = CGPointMake(0,0);

}
效果2.gif
  1. 隐式动画
    注意看上面的gif 可以感觉出来有动画的效果,就是移动过去的,为什么呢,这是因为 手动创建的图层都会自带一个动画效果

也就是非根层

那么什么是根层呢 每一个View 内部都默认关联一个 CALayer我们称这个layer 为RootLayer->根层

非根层 - > 手动创建的 CALayer对象都存在隐式动画

可以通过 动画事务对隐式动画进行操作

//关闭 /打开 隐式动画
 [CATransaction setDisableActions:NO];

控制隐式动画

    [CATransaction begin];
    [CATransaction setDisableActions:NO];
//动画时长
    [CATransaction setAnimationDuration:2];
    self.layer.position = CGPointMake(100, 400);
    self.layer.bounds = CGRectMake(0, 0, 90, 90);
    self.layer.backgroundColor = [UIColor redColor].CGColor;
//结束
    [CATransaction commit];

三 : CoreAnimation 和其子类

子类解析.png

我们分析一下这个子类结构图
CAMediaTiming是它们共同遵守的一个协议
CATransition 是我们熟悉的转场动画
CABasicAnimation是一个值到另一个值
CAKeyframeAnimation一个值到多个值

  1. 了解

要想使用 CoreAnimation 我们先要有CALayer 因为CoreAnimation 只作用在 CALayer 上有效果

通过创建 CAAnimation对象 并且设置动画属性

最后在layer 层上添加 动画 就OK 了

2 位移动画

平移.gif
 //1.创建动画对象(设置layer 的属性值)
    CABasicAnimation *anmi = [CABasicAnimation animation];
    //2.设置属性
    anmi.keyPath = @"position.x";
    anmi.toValue = @300;
    
    //动画完成时,会自动删除动画
    anmi.removedOnCompletion = NO;
    anmi.fillMode = kCAFillModeForwards;
    //    anmi.fillMode = @"forwards";
    //3.添加动画
    [self.TZview.layer addAnimation:anmi forKey:nil];
  1. 放大缩小动画
心跳.gif
 //-------心跳部分
    //创建动画
    CABasicAnimation *heartanmi = [CABasicAnimation animation];
    //设置属性值
    heartanmi.keyPath = @"transform.scale";
    heartanmi.toValue = @0;
    
    //设置动画执行次数
    heartanmi.repeatCount = MAXFLOAT;
    
    //动画执行时长
    heartanmi.duration = 0.7;
    
    //自动反转效果(怎样去,怎样回)
    heartanmi.autoreverses = YES;
    
    //添加动画
    [self.heartImage.layer addAnimation:heartanmi forKey:nil];
  1. 指定路径位移
路径移动.gif
CAKeyframeAnimation *Anmi = [CAKeyframeAnimation animation];
    Anmi.duration = 2;
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(50, 50)];
    [path addLineToPoint:CGPointMake(300, 50)];
    [path addLineToPoint:CGPointMake(300, 400)];
    Anmi.keyPath = @"position";
    Anmi.path = path.CGPath;
    [self.boheImgeView.layer addAnimation:Anmi forKey:nil];
  1. 删除图标动画
抖动.gif
 CAKeyframeAnimation *boheAnmi = [CAKeyframeAnimation animation];
    //设置属性
    boheAnmi.keyPath = @"transform.rotation";
    //    boheAnmi.values = @[@(angleToRad(-5)),@(angleToRad(5))];
    
    boheAnmi.values = @[@(angleToRad(-5)),@(angleToRad(5)),@(angleToRad(-5))];
    
    //动画执行次数
    boheAnmi.repeatCount = MAXFLOAT;
    //反转
    [self.boheImgeView.layer addAnimation:boheAnmi forKey:nil];
  1. 转场动画
转场.gif
-(void)animationMove{
    //添加转场动画
    CATransition *anmi = [CATransition animation];
    
    anmi.duration = 1;
    
    //设置转场类型 立体
//    anmi.type = @"cube";
    
    //水滴
    //    anmi.type = @"rippleEffect";
    
    //翻页效果
    //    anmi.type = @"pageCurl";
    
    //平推效果
    //    anmi.type = @"push";
    
    //收缩效果
    anmi.type = @"suckEffect";
    
    //动画起始位置
    anmi.startProgress = 0.3;
    //动画结束位置
    anmi.endProgress = 0.5;
    [self.TZimageView.layer addAnimation:anmi forKey:nil];

}

点击

-(void)animationSelecImage{
    _i++;
    if (_i == 4) {
        _i = 1;
        
    }
    NSString *imageName = [NSString stringWithFormat:@"%d",_i];
    self.TZimageView.image = [UIImage imageNamed:imageName];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    [self animationSelecImage];
    
    
    [self animationMove];
    
    
}
  1. 复制层
打地鼠.gif
@property (strong, nonatomic) IBOutlet UIView *showView;
 //复制层
    CAReplicatorLayer *rel = [CAReplicatorLayer layer];
    rel.frame = self.showView.bounds;
    [self.showView.layer addSublayer:rel];
    
//赋值份数    
rel.instanceCount = 5;
    
    
    //创建一个震动条
    
    
    CALayer *layer = [CALayer layer];
    layer.contents = (id)[UIImage imageNamed:@"dishu.jpg"].CGImage;
    layer.backgroundColor = [UIColor redColor].CGColor;
//    layer.frame = CGRectMake(0, self.showView.bounds.size.height - 100, 30, 100);
    layer.bounds = CGRectMake(0, 0, 30, 100);
    layer.anchorPoint = CGPointMake(0, 1);
    layer.position = CGPointMake(0, self.showView.bounds.size.height);
    [rel addSublayer:layer];
    
    
    //添加动画
    CABasicAnimation *anmi = [CABasicAnimation animation];
    anmi.keyPath = @"transform.scale.y";
    anmi.toValue = @0;
    anmi.repeatCount = MAXFLOAT;
    anmi.autoreverses = YES;
    anmi.duration = 0.3;
    [layer addAnimation:anmi forKey:nil];
    
    
    rel.instanceTransform = CATransform3DMakeTranslation(45, 0, 0);
    //子层动画延迟执行
    rel.instanceDelay = 1;

解析 : 有的人会对 layer.anchorPoint = CGPointMake(0, 1); 不理解 这样解释,所有的动画效果都是 围绕着锚点为中心进行动画的,默认的锚点为(0.5 , 0.5) 我们为了实现效果 要移动锚点的位置.

rel.instanceTransform = CATransform3DMakeTranslation(45, 0, 0); 这个设置的含义是 ,当我们没有设置的时候 所有的复制层全都叠加在一起,当设置后 ,对复制出来的子层做形变操作,每一个是相对于上一个子层做的形变

  1. 倒影效果
倒影.png

我们先自己定义一下关联 一下 self.view 目的是直接给我们返回一个复制层的layer

@interface TZview : UIView

@end
@implementation TZview

//返回当前UIview内容layer 类型
+(Class)layerClass{

    return  [CAReplicatorLayer class];
    
}
@end

- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor lightGrayColor];
    CAReplicatorLayer *repl = (CAReplicatorLayer *)self.view.layer;
    repl.instanceCount = 2;
    
    //绕着复制曾的锚点进行旋转
    repl.instanceTransform = CATransform3DMakeRotation(M_PI, 1, 0, 0);
     
    //阴影 把所有颜色减淡
    repl.instanceRedOffset -= 0.2;
    repl.instanceGreenOffset -= 0.2;
    repl.instanceBlueOffset -= 0.2;
    repl.instanceAlphaOffset -= 0.2;
    
}

解析 : 这个的注意点 就是 instanceTransform这个属性设置时候 是 绕着复制曾的锚点进行旋转

  1. 手写动画效果
手写动画.gif

想把图片换成血滴 怕有些同学不适应,仿造聂风成魔时候的feel.

首先我们要自定义一个view 替换系统 self.view 先完成手写板部分功能.

#import 

@interface TZdrawView : UIView


-(void)start;

-(void)redraw;

@end
#import "TZdrawView.h"

@interface TZdrawView()
@property(nonatomic,strong)UIBezierPath *path;
@property(nonatomic,weak)CALayer *dotlayer;
@end
@implementation TZdrawView

(1) 添加手势 完成 手写板功能

-(void)awakeFromNib{
    
    [super awakeFromNib];
    
    //添加手势 创建路径
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
    
    [self addGestureRecognizer:pan];

 UIBezierPath *path = [UIBezierPath bezierPath];
    self.path = path;

}
-(void)pan:(UIPanGestureRecognizer*)pan{

    //获取当前点
   CGPoint curp = [pan locationInView:self];
    if (pan.state == UIGestureRecognizerStateBegan) {
       
        //设置启点
        [self.path moveToPoint:curp];
        
    }else if (pan.state == UIGestureRecognizerStateChanged){
    
    
    //添加一根线到当前点
        [self.path addLineToPoint:curp];
        
        //重绘图
        [self setNeedsDisplay];
        
    }
}
-(void)drawRect:(CGRect)rect{

    //绘制路径
    [self.path stroke];
    
}

解析 : 当我们调用 [self setNeedsDisplay]; 就会触发 drawRect 方法

(2) 绘制 聂风 成魔时候的花瓣效果

首先把花瓣layer 添加上

-(void)awakeFromNib{
    
    [super awakeFromNib];
    
    //添加手势
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
    
    [self addGestureRecognizer:pan];
    
    //添加粒子
    CALayer *dotlayer = [CALayer layer];
    dotlayer.frame = CGRectMake(0, -20, 20, 20);
//    dotlayer.backgroundColor = [UIColor redColor].CGColor;
    dotlayer.contents = (id)[UIImage imageNamed:@"flower"].CGImage;
    
    self.dotlayer = dotlayer;
    [self.layer addSublayer:dotlayer];
    

    //复制层
    CAReplicatorLayer *repl = (CAReplicatorLayer*)self.layer;
    repl.instanceCount = 30;
    //设置动画演延时执行时长
    repl.instanceDelay = 0.1;
    // //创建路径,设置启点
    UIBezierPath *path = [UIBezierPath bezierPath];
    self.path = path;
    
}

让自己成为复制层

//成为复制层
+(Class)layerClass{

    return [CAReplicatorLayer class];
    
}

开始绘制动画

-(void)start{

    CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
    anim.keyPath = @"position";
    anim.path = self.path.CGPath;
    anim.repeatCount = MAXFLOAT;
    anim.duration = 13;
    [self.dotlayer addAnimation:anim forKey:nil];
    
}

(3)重新绘制功能

-(void)redraw{


    //删除动画
    [self.dotlayer removeAllAnimations];
    
    //删除路径
    [self.path removeAllPoints];
    
    //重绘制
    [self setNeedsDisplay];
    
}

(4)最后就是把封装好的画板给我们的控制器用,这步就省略了.

四 : 实例解析未读消息移除动画

QQ移除消息.gif

这个功能我们主要用到的一个图层叫 CAShapeLayer
这个图层的作用就是控制形变.我们先来分析一下这个功能的结构图

图解分析 .jpg

根据简单的 同位角角相等 和内错角相等 还有一些正余弦知识我们可以了解到 各个点的位置

解析 : 有的人会问 为什么 A点坐标 那个 为什么 y1 + r1 * sinθ
为什么不是 y1 - r1 * sinθ
因为当我们手指移动时候 这个 cosθ 是变化的 所以正负不一样,你也可以写成 y1 - r1 * sinθ 但是此时按照某一时刻的分析 我们暂且这么做.

(1)首先我们自定义一个btn 按钮


@interface TZmessageBtn : UIButton

@end
#import "TZmessageBtn.h"

@interface TZmessageBtn()
@property(nonatomic,weak)UIView *smallcircle;
@property(nonatomic,strong)CAShapeLayer *shapL;

@end

(2)添加移动手势 和 初始化视图

-(void)awakeFromNib{
    [super awakeFromNib];
    
    [self setUp];
    
    //添加手势
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
    [self addGestureRecognizer:pan];
    
    
}
-(void)setUp{

   //圆角
    self.layer.cornerRadius = self.bounds.size.width * 0.5;
    
    
    //设置背景颜色
    [self setBackgroundColor:[UIColor blueColor]];
    
    
    [self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    
    self.titleLabel.font = [UIFont systemFontOfSize:12];
    
    
    //添加小圆
    UIView *smallcircle = [[UIView alloc]initWithFrame:self.frame];
    smallcircle.layer.cornerRadius = self.layer.cornerRadius;
    smallcircle.backgroundColor = self.backgroundColor;
    self.smallcircle = smallcircle;
    [self.superview addSubview:smallcircle];
    
    
    //把一个UIView添加到指定的位置
    
    [self.superview insertSubview:smallcircle belowSubview:self];
    
}

(3).两个圆 根据拖动计算距离

//求两个圆之间的距离

-(CGFloat)distanceWithSmallCircle:(UIView*)smallCircle BigCircle:(UIView*)bigcircle{

     //x轴方向偏移量
    CGFloat offsetX = bigcircle.center.x - smallCircle.center.x;
    
    //y轴方向偏移量

    CGFloat offsetY = bigcircle.center.y - smallCircle.center.y;

  return   sqrt(offsetX * offsetX + offsetY * offsetY);
    

    
}

(4)计算不规则的弧形

-(UIBezierPath*)pathWithSmallCircle:(UIView*)smallCircle BigCircle:(UIView*)bigcircle{

    CGFloat x1 = smallCircle.center.x;
    CGFloat y1 = smallCircle.center.y;
    
    CGFloat x2 = bigcircle.center.x;
    CGFloat y2 = bigcircle.center.y;
    
    CGFloat d = [self distanceWithSmallCircle:smallCircle BigCircle:bigcircle];
    
    
    if (d <= 0) {
        return nil;
        
    }
    
    
    
    //------------
    CGFloat cosθ = (y2 - y1) / d;
    CGFloat sinθ = (x2 - x1) / d;
    CGFloat r1 = smallCircle.bounds.size.width * 0.5;
    CGFloat r2 = bigcircle.bounds.size.width * 0.5;
    
    
    
    
    //描述点
    //A点
    CGPoint pointA =  CGPointMake(x1 - r1 *cosθ, y1 + r1 * sinθ);
    
    //B点
    CGPoint pointB = CGPointMake(x1 + r1 * cosθ, y1 - r1 * sinθ);
    
    //C点
    CGPoint pointC = CGPointMake(x2 + r2 * cosθ, y2 - r2 * sinθ);
    
    //D点
    
    CGPoint pointD = CGPointMake(x2 - r2 * cosθ, y2 + r2 * sinθ);
    
    //  O点
    CGPoint pointO = CGPointMake(pointA.x + d * 0.5 * sinθ, pointA.y + d * 0.5 * cosθ);
    //P点
    CGPoint pointP = CGPointMake(pointB.x + d * 0.5 * sinθ, pointB.y + d * 0.5 * cosθ);
    
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    //AB
    [path moveToPoint:pointA];
    [path addLineToPoint:pointB];
    
    //BC(曲线)
    [path addQuadCurveToPoint:pointC controlPoint:pointP];
    
    //CD
    [path addLineToPoint:pointD];
    
    //DA(曲线);
    [path addQuadCurveToPoint:pointA controlPoint:pointO];
    
    return path;
    
}

(5)设置按钮高亮情况

// 取消高亮
-(void)setHighlighted:(BOOL)highlighted{


}

(6)懒加载 图形图层

-(CAShapeLayer *)shapL{

    if (_shapL == nil) {
        
        
        _shapL = [CAShapeLayer layer];
        _shapL.fillColor = [UIColor blueColor].CGColor;
        //形状图层
        [self.superview.layer insertSublayer:_shapL atIndex:0];

    }
    return _shapL;
}

(7)拖动事件

-(void)pan:(UIPanGestureRecognizer*)pan{

   //拖动
   CGPoint transp =  [pan translationInView:self];
    
    //transform 并没有修改center 修改的是frame
//    self.transform = CGAffineTransformTranslate(self.transform, transp.x, transp.y);
    
    CGPoint center = self.center;
    center.x += transp.x;
    center.y += transp.y;
    self.center = center;
    
    //复位
    [pan setTranslation:CGPointZero inView:self];
    
    
    CGFloat distance = [self distanceWithSmallCircle:self.smallcircle BigCircle:self];
    
    //小圆半径根据距离增大半径减小
    CGFloat smallR = self.bounds.size.width * 0.5;
    smallR -= distance/10.0;
    self.smallcircle.bounds = CGRectMake(0, 0, smallR * 2, smallR * 2);
    self.smallcircle.layer.cornerRadius = smallR ;
    
    
    //形状图层
    UIBezierPath *path = [self pathWithSmallCircle:self.smallcircle BigCircle:self];
    
    
    
    if (self.smallcircle.hidden == NO) {
        self.shapL.path = path.CGPath;
        
        
    }
         if (distance > 60) {
        //小圆隐藏,路径隐藏
        self.smallcircle.hidden = YES;
        [self.shapL removeFromSuperlayer];
             self.shapL = nil;
    }
    
    
    
   // 手指松开
    if (pan.state == UIGestureRecognizerStateEnded) {
        //判断结束时是否大于60
        if (distance >= 60) {
         //让按钮消失
            
            //播放动画消失
            UIImageView *imagev = [[UIImageView alloc]initWithFrame:self.bounds];
            [self addSubview:imagev];
            NSMutableArray *Array = [NSMutableArray array];
            for (int i = 0; i < 8; i++) {
             UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"%d",i+1]];
                
                [Array addObject:image];
            }
            imagev.animationImages = Array;
            [imagev startAnimating];
           
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [self removeFromSuperview];
                
            });
        
        }else{
          //复位操作
            [self.shapL removeFromSuperlayer];
            
            self.shapL = nil;
            // 还原位置
            [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.2 initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{
                
                //设置大圆中心点位置
                self.center = self.smallcircle.center;

            } completion:^(BOOL finished) {
                // 显示小圆
                self.smallcircle.hidden = NO;
            }];

        }
    }
    
}

解析 我们对于变化的计算方式通常是求出极值,然后再计算响应比例.

(8) 引用自定义按钮 并且 VC取消autolayout

self.view.translatesAutoresizingMaskIntoConstraints = NO;

五 : 总结

对于动画效果,我们不必过多的追求极端和完美,我们只要做好最基础的,好的效果就迎刃而解了.
我们还应该了解什么时候使用核心动画 什么时候 使用我们的UI动画

(1) 当我们动画只作用在Layer 层的时候
(2)我们核心的动画看到的都是假象,因真正的view 并没有发生变化.
(3)当我们不需要与用户进行交互的时候 使用核心动画
(4)我们使用根据路径做动画,还要转场动画时候 用核心动画.
我们先掌握这些简单的动画效果和基础知识,才能做出更漂亮的动画.

//下期 - 算法篇-再续.

你可能感兴趣的:(iOS篇-UI篇-CoreAnimation(核心动画))