美文网首页动画iOS头条干货iOS学习笔记
iOS篇-UI篇-CoreAnimation(核心动画)

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

作者: TianTianBaby223 | 来源:发表于2017-07-28 17:53 被阅读452次

    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<UITouch *> *)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<UITouch *> *)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<UITouch *> *)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 <UIKit/UIKit.h>
    
    @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(核心动画)

        本文链接:https://www.haomeiwen.com/subject/elnskxtx.html