美文网首页
Lottie 动画 官方用法 分析

Lottie 动画 官方用法 分析

作者: wangDavid939i | 来源:发表于2018-12-01 16:20 被阅读0次
    #import "AnimationExplorerViewController.h"
    #import "JSONExplorerViewController.h"
    #import "LAQRScannerViewController.h"
    #import <Lottie/Lottie.h>
    
    typedef enum : NSUInteger {
      ViewBackgroundColorWhite,
      ViewBackgroundColorBlack,
      ViewBackgroundColorGreen,
      ViewBackgroundColorNone
    } ViewBackgroundColor;
    
    @interface AnimationExplorerViewController ()
    
    @property (nonatomic, assign) ViewBackgroundColor currentBGColor;
    @property (nonatomic, strong) UIToolbar *toolbar;
    @property (nonatomic, strong) UISlider *slider;
    
    /**
     动画承载视图
     */
    @property (nonatomic, strong) LOTAnimationView *laAnimation;
    
    @end
    
    @implementation AnimationExplorerViewController
    
    - (void)setCurrentBGColor:(ViewBackgroundColor)currentBGColor {
      _currentBGColor = currentBGColor;
      switch (currentBGColor) {
        case ViewBackgroundColorWhite:
          self.view.backgroundColor = [UIColor whiteColor];
          break;
        case ViewBackgroundColorBlack:
          self.view.backgroundColor = [UIColor blackColor];
          break;
        case ViewBackgroundColorGreen:
          self.view.backgroundColor = [UIColor colorWithRed:50.f/255.f
                                                      green:207.f/255.f
                                                       blue:193.f/255.f
                                                      alpha:1.f];
          break;
        case ViewBackgroundColorNone:
          self.view.backgroundColor = nil;
          break;
        default:
          break;
      }
    }
    
    - (void)viewDidLoad {
      [super viewDidLoad];
      
      self.currentBGColor = ViewBackgroundColorWhite;
      self.toolbar = [[UIToolbar alloc] initWithFrame:CGRectZero];
      
      UIBarButtonItem *open = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:@selector(_open:)];
      UIBarButtonItem *flx1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
        //分享转发按钮 —— (需要 调用 “URL” 的方法来助推)
      UIBarButtonItem *openWeb = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(_showURLInput)];
      UIBarButtonItem *flx2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
      UIBarButtonItem *play = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPlay target:self action:@selector(_play:)];
      UIBarButtonItem *flx3 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
      UIBarButtonItem *loop = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(_loop:)];
      UIBarButtonItem *flx4 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
      UIBarButtonItem *zoom = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(_setZoom:)];
      UIBarButtonItem *flx5 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
      UIBarButtonItem *bgcolor = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCompose target:self action:@selector(_setBGColor:)];
      UIBarButtonItem *flx6 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
      UIBarButtonItem *close = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop target:self action:@selector(_close:)];
      self.toolbar.items = @[open, flx1, openWeb, flx2, loop, flx3, play, flx4, zoom, flx5, bgcolor, flx6, close];
      [self.view addSubview:self.toolbar];
      [self resetAllButtons];
      
      self.slider = [[UISlider alloc] initWithFrame:CGRectZero];
      [self.slider addTarget:self action:@selector(_sliderChanged:) forControlEvents:UIControlEventValueChanged];
      self.slider.minimumValue = 0;
      self.slider.maximumValue = 1;
      [self.view addSubview:self.slider];
    }
    
    • 重新设置 所有按钮 的 显示效果
    - (void)resetAllButtons {
      self.slider.value = 0;
      for (UIBarButtonItem *button in self.toolbar.items) {
        [self resetButton:button highlighted:NO];
      }
    }
    
    • 设置播放按钮的 颜色 (通过bool值来判断 当前按钮的 状态并为之赋予不同的颜色)
    - (void)resetButton:(UIBarButtonItem *)button highlighted:(BOOL)highlighted {
        
        //通过三目运算符来判断当前按钮的所处状态 点击“播放”后为黑色 :“其余按钮” 颜色为 “ :” 后的颜色
      button.tintColor = highlighted ? [UIColor blackColor] : [UIColor colorWithRed:50.f/255.f
                                                                            green:207.f/255.f
                                                                             blue:193.f/255.f
                                                                            alpha:1.f];
        NSLog(@"播放按钮 当前 所处 状态为 :%@",highlighted ? @"黑色" : @"绿色");
    }
    
    - (void)viewWillLayoutSubviews {
      [super viewWillLayoutSubviews];
      CGRect b = self.view.bounds;
      self.toolbar.frame = CGRectMake(0, b.size.height - 44, b.size.width, 44);
      CGSize sliderSize = [self.slider sizeThatFits:b.size];
      sliderSize.height += 12;
      self.slider.frame = CGRectMake(10, CGRectGetMinY(self.toolbar.frame) - sliderSize.height, b.size.width - 20, sliderSize.height);
      self.laAnimation.frame = CGRectMake(0, 0, b.size.width, CGRectGetMinY(self.slider.frame));
    }
    
    • 监听到 进度条的 位置 改变时 动态赋值给当前的 进度条 以 实时改变 UI
    - (void)_sliderChanged:(UISlider *)slider {
        
        
      self.laAnimation.animationProgress = slider.value;
        NSLog(@"%f",slider.value);
    }
    
    
    - (void)_open:(UIBarButtonItem *)button {
      [self _showJSONExplorer];
    }
    
    
    • 自己定义的枚举类型方法 ——(里面是三个 不同的 视图 显示位置类型)
    - (void)_setZoom:(UIBarButtonItem *)button {
      switch (self.laAnimation.contentMode) {
        case UIViewContentModeScaleAspectFit: {
          self.laAnimation.contentMode = UIViewContentModeScaleAspectFill;
          [self showMessage:@"Aspect Fill"];
        }  break;
        case UIViewContentModeScaleAspectFill:{
          self.laAnimation.contentMode = UIViewContentModeScaleToFill;
          [self showMessage:@"Scale Fill"];
        }
          break;
        case UIViewContentModeScaleToFill: {
          self.laAnimation.contentMode = UIViewContentModeScaleAspectFit;
          [self showMessage:@"Aspect Fit"];
        }
          break;
        default:
          break;
      }
    }
    
    - (void)_setBGColor:(UIBarButtonItem *)button {
      ViewBackgroundColor current = self.currentBGColor;
      current += 1;
      if (current == ViewBackgroundColorNone) {
        current = ViewBackgroundColorWhite;
      }
      self.currentBGColor = current;
    }
    
    • 通过“URL”的方式来获取 动画 的 内容文件 并解析
    - (void)_showURLInput {
      LAQRScannerViewController *qrVC = [[LAQRScannerViewController alloc] init];
        
      [qrVC setCompletionBlock:^(NSString *selectedAnimation) {
        if (selectedAnimation) {
            //调用 下面当中的 “URL” 的方法
          [self _loadAnimationFromURLString:selectedAnimation];
        }
        [self dismissViewControllerAnimated:YES completion:NULL];
      }];
        
      UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:qrVC];
        
      [self presentViewController:nav animated:YES completion:NULL];
    }
    
    • 跳转到 列表 界面
    - (void)_showJSONExplorer {
        //跳转到 列表 界面
      JSONExplorerViewController *vc = [[JSONExplorerViewController alloc] init];
        
        
        //让 该控制器“vc” 去调动 一个 block的 回传属性方法
      [vc setCompletionBlock:^(NSString *selectedAnimation) {
        if (selectedAnimation) {
            //并把 点中的 row cell的 动画名字 回传过去
          [self _loadAnimationNamed:selectedAnimation];
            NSLog(@"点中动画的名字:%@",selectedAnimation);
        }
          //执行完上边的block的方法后,自动向下弹走控制器
        [self dismissViewControllerAnimated:YES completion:NULL];
      }];
        
        //把 ”列表“ 控制器 设置为 根视图控制器
      UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:vc];
        //弹出模态ViewController(弹出控制器)
      [self presentViewController:navController animated:YES completion:NULL];
    }
    
    - (void)_loadAnimationFromURLString:(NSString *)URL {
        //跟下一个方法中的 意思 类同
      [self.laAnimation removeFromSuperview];
      self.laAnimation = nil;
      [self resetAllButtons];
      
        
        //跟下一个 方法中 不同的是 改方法中 是通过 “URL” 的路径字符串来 初始化 动画承载视图
      self.laAnimation = [[LOTAnimationView alloc] initWithContentsOfURL:[NSURL URLWithString:URL]];
      self.laAnimation.contentMode = UIViewContentModeScaleAspectFit;
      [self.view addSubview:self.laAnimation];
      [self.view setNeedsLayout];
        
    }
    
    • 移除 “动画承载视图” 上的现有内容 并 赋值为空 (nil)
    • 不然~ 你将无法 选择 下一个 动画 展示在 视图上 ,因为 当前的 视图上已经有了 内容 并且你没有 及时 移除掉!
    //上方block 中 所调用的方法
    - (void)_loadAnimationNamed:(NSString *)named {
        //移除 “动画承载视图” 上的现有内容 并 赋值为空 (nil)
        //不然~ 你将无法 选择 下一个 动画 展示在 视图上 ,因为 当前的 视图上已经有了 内容 并且你没有 及时 移除掉!
      [self.laAnimation removeFromSuperview];
      self.laAnimation = nil;
        
        
        //将所有的 按钮 位置 复原 —— (尤其是 时间进度条上的button,通过复原。使其值 变为 “0”,这样滑块 自然 处于 开始的位置)
        //!!注意:如果不复原,滑块按钮 将位于 时间进度条的左右边既动画结束的位置!!
      [self resetAllButtons];
      
        
        //将上面 通过 点击某行 所传过来的 动画json文件名字 获取到 并 调用方法解析完后 满屏加载到 合适的 位置
      self.laAnimation = [LOTAnimationView animationNamed:named];
      self.laAnimation.contentMode = UIViewContentModeScaleAspectFit;
      [self.view addSubview:self.laAnimation];
        
        
        //将所需要的动画 加载到 当前视图 ——(此方法可写可不写)
      [self.view setNeedsLayout];
    }
    

    重绕方法 —— (此方法 该类中 并没有 实际调用到,所以 可写可不写。不影响操作~)

    - (void)_rewind:(UIBarButtonItem *)button {
        //设置动画重载视图的 “进度”
        //实现原理是将 后期 更改的 赋值给 之前的 进度属性
      self.laAnimation.animationProgress = 0.5;
    }
    

    CADisplayLink是用于同步屏幕刷新频率的计时器,在开发中我们经常会遇到使用计时器的情况,例如图片轮播,进度条的绘制等就是比较常见的应用场景.

    从runloop中移除

    移除计时器有两个方法:
    -- (void)removeFromRunLoop:(NSRunLoop *)runloop forMode:(NSRunLoopMode)mode 和
    -- (void)invalidate.

    我们来分析一下他们的异同

    removeFromRunLoop: forMode:会将接收者从给定的模式中移除,这个方法会对计时器进行隐式的release.
    在调用removeFromRunloop方法,需要做判断,如果当期计时器不在runloop的话,会出现野指针的crash.
    出现crash的原因是runloop多次调用了release方法,进行了over-release.

    -- (void)invalidate是从runloop所有模式中移除计时器,并取消计时器和target的关联关系.多次调用这个方法,不会出现crash.

             
    
    - (void)_play:(UIBarButtonItem *)button {
        // isAnimationPlaying —— 播放动画时标志为YES 为 Bool 类型
        //当检测到 该动画为 点击 “播放” 按钮后 即将进入 (动画正在播放ing) 的状态并执行下面的语句
      if (self.laAnimation.isAnimationPlaying) {
          //当处于(动画正在播放ing)的 状态时 再次点击 “播放” 按钮时 将会 暂停 "滑块" 以及 "动画" 并将 "播放" 按钮的颜色 改变~
          
          //此刷新 按钮状态的 方法 可写可不写 并没任何影响
        [self resetButton:button highlighted:NO];
          
          
        [self.laAnimation pause];
      } else {
          //CADisplayLink是用于同步屏幕刷新频率的计时器,在开发中我们经常会遇到使用计时器的情况,例如图片轮播,进度条的绘制等就是比较常见的应用场景.
    
        CADisplayLink *displayLink =[CADisplayLink displayLinkWithTarget:self selector:@selector(_updateSlider)] ;
          
        [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
          //在此处,才是真正的 改变 “播放” 按钮的 颜色 状态
        [self resetButton:button highlighted:YES];
          
        [self.laAnimation playWithCompletion:^(BOOL animationFinished) {
            //每个计时器对象只能加入到一个runloop中,但是可以被添加到不同的模式中,当CADisplayLink被加入到runloop时,会被runloop隐式retain.如果想从所有的模式中移除计时器,需要执行-invalidate()方法.
           
          [displayLink invalidate];
            
          [self resetButton:button highlighted:NO];
        }];
      }
    }
    
    - (void)_updateSlider {
        //刷新 进度条的 变化
        //将 当前 动画 的 播放进度 赋值给 进度条的 Value 值
      self.slider.value = self.laAnimation.animationProgress;
    }
    
    - (void)_loop:(UIBarButtonItem *)button {
      self.laAnimation.loopAnimation = !self.laAnimation.loopAnimation;
        // loopAnimation :告诉动画 无限循环 —— 默认为NO
        [self resetButton:button highlighted:self.laAnimation.loopAnimation];
        
        //通过判断 按钮点击的 呈现状态(重复:不重复)
        //来展示消息提示框 (Loop Enabled循环过程中" : @"Loop Disabled终止循环播放)
      [self showMessage:self.laAnimation.loopAnimation ? @"Loop Enabled循环过程中" : @"Loop Disabled终止循环播放"];
    }
    
    - (void)_close:(UIBarButtonItem *)button {
        
      [self.presentingViewController dismissViewControllerAnimated:YES completion:NULL];
        
    }
    
    - (void)showMessage:(NSString *)message {
      UILabel *messageLabel = [[UILabel alloc] initWithFrame:CGRectZero];
      messageLabel.textAlignment = NSTextAlignmentCenter;
      messageLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
      messageLabel.textColor = [UIColor whiteColor];
      messageLabel.text = message;
      
      CGSize messageSize = [messageLabel sizeThatFits:self.view.bounds.size];
      messageSize.width += 14;
      messageSize.height += 14;
      messageLabel.frame = CGRectMake(10, 30, messageSize.width, messageSize.height);
      messageLabel.alpha = 0;
      [self.view addSubview:messageLabel];
      
      [UIView animateWithDuration:0.3 animations:^{
        messageLabel.alpha = 1;
      } completion:^(BOOL finished) {
        [UIView animateWithDuration:0.3 delay:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
          messageLabel.alpha = 0;
        } completion:^(BOOL finished) {
          [messageLabel removeFromSuperview];
        }];
      }];
    }
    
    
    @end
    

    相关文章

      网友评论

          本文标题:Lottie 动画 官方用法 分析

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