lottie-ios-bb 2.5.4

lottie-ios-bb 2.5.4

Richard 维护。



  • Richard

Lottie for iOS, macOS (以及 AndroidReact Native)

目录

简介

Lottie 是一个适用于 Android 和 iOS 的移动库,它通过 Adobe After Effects 以 json 格式导出并使用 bodymovin 解析,然后在移动端和通过 React Native 上原生渲染矢量动画!

首次,设计师可以创建并运输美观的动画,无需工程师费尽周折地手工重现。由于动画由JSON支持,它们体积极小,但在复杂度方面却可以很大!动画可以播放、调整大小、循环、加速、减速、逆放,甚至可以交互式刮擦。Lottie还可以播放或循环动画的任一部分,可能性无穷!甚至可以在运行时以各种方式更改动画!改变颜色、位置或任何可关键帧化的值!Lottie还可以默认支持原生UIViewController转换!

这只是展示了Lottie的强大功能的一小部分

Example1 Example2

Example3

Abcs

安装Lottie

GitHub 代码库

您可以从Lottie GitHub代码库克隆源代码,并将Lottie.xcodeproj添加以构建动态库或静态库。

CocoaPods

获取CocoaPods,并将pod添加到您的Podfile中

pod 'lottie-ios'

运行

pod install

将 Cocoapod 安装到项目中后,导入Lottie(Objective-C:使用 #import <Lottie/Lottie.h>;Swift: 使用 import Lottie

Carthage

获取Carthage

在Cartfile中添加Lottie

github "airbnb/lottie-ios" "master"

运行

carthage update

在应用程序的目标中,“常规”选项卡下,“链接框架和库”部分,从Carthage/Build/iOS目录拖拽lottie-ios.framework到由carthage update生成的框架中。

iOS示例应用程序

克隆此仓库并尝试运行示例应用程序。此仓库可以构建macOS示例和iOS示例。

iOS示例应用程序演示了Lottie的多个功能

Example 1Example 2 Example 3

动画浏览器允许您刮擦、播放、循环和调整动画的大小。可以从应用程序包或使用内置二维码扫描仪从Lottie Files加载动画。

macOS示例应用程序

克隆此仓库并尝试运行示例应用程序。此仓库可以构建macOS示例和iOS示例。

Lottie Viewer

macOS版Lottie查看器允许您将JSON文件拖放以打开、播放、刮擦和循环动画。该应用程序使用与iOS应用程序相同的动画代码,因此您将获得Mac和iOS动画的准确表示。

Objective-C示例

Lottie动画可以从捆绑的JSON或从URL加载。要将JSON捆绑在一起,只需将其添加到xcode中的目标项目,并提供动画所需的任何图像。

LOTAnimationView *animation = [LOTAnimationView animationNamed:@"Lottie"];
[self.view addSubview:animation];
[animation playWithCompletion:^(BOOL animationFinished) {
  // Do Something
}];

如果您正在处理多个包,您可以。

LOTAnimationView *animation = [LOTAnimationView animationNamed:@"Lottie" inBundle:[NSBundle YOUR_BUNDLE]];
[self.view addSubview:animation];
[animation playWithCompletion:^(BOOL animationFinished) {
  // Do Something
}];

或者您可以从NSURL程序化地加载它

LOTAnimationView *animation = [[LOTAnimationView alloc] initWithContentsOfURL:[NSURL URLWithString:URL]];
[self.view addSubview:animation];

Lottie支持iOS的UIViewContentModes属性, аспектFit、aspectFill和scaleFill

您还可以交互式地设置动画进度。

CGPoint translation = [gesture getTranslationInView:self.view];
CGFloat progress = translation.y / self.view.bounds.size.height;
animationView.animationProgress = progress;

或者您可以播放动画的一部分

[lottieAnimation playFromProgress:0.25 toProgress:0.5 withCompletion:^(BOOL animationFinished) {
  // Do Something
}];

Swift示例

Lottie动画可以从捆绑的JSON或从URL加载。要将JSON捆绑在一起,只需将其添加到xcode中的目标项目,并提供动画所需的任何图像。

let animationView = LOTAnimationView(name: "LottieLogo")
self.view.addSubview(animationView)
animationView.play{ (finished) in
  // Do Something
}

如果您的动画在另一个包中,您可以使用

let animationView = LOTAnimationView(name: "LottieLogo" bundle:yourBundle)
self.view.addSubview(animationView)
animationView.play()

或者您可以从URL异步加载它

let animationView = LOTAnimationView(contentsOf: WebURL)
self.view.addSubview(animationView)
animationView.play()

您还可以交互式地设置动画进度。

let translation = gesture.getTranslationInView(self.view)
let progress = translation.y / self.view.bounds.size.height;
animationView.animationProgress = progress

或者您可以播放动画的一部分

animationView.play(fromProgress: 0.25, toProgress: 0.5, withCompletion: nil)

iOS控制器过渡

Lottie提供了一个用于制作自定义viewController转换的UIViewController动画控制器!

Transition1 Transition2

只需成为转换的代理

- (void)_showTransitionA {
  ToAnimationViewController *vc = [[ToAnimationViewController alloc] init];
  vc.transitioningDelegate = self;
  [self presentViewController:vc animated:YES completion:NULL];
}

然后使用LOTAnimationTransitionController实现代理方法

#pragma mark -- View Controller Transitioning

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
  LOTAnimationTransitionController *animationController = [[LOTAnimationTransitionController alloc] initWithAnimationNamed:@"vcTransition1" fromLayerNamed:@"outLayer" toLayerNamed:@"inLayer" applyAnimationTransform:NO];
  return animationController;
}

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
  LOTAnimationTransitionController *animationController = [[LOTAnimationTransitionController alloc] initWithAnimationNamed:@"vcTransition2" fromLayerNamed:@"outLayer" toLayerNamed:@"inLayer" applyAnimationTransform:NO];
  return animationController;
}

通过设置applyAnimationTransform为YES,可以让Lottie动画移动from和to视图控制器。它们将位于层的原点位置。当设置为NO时,Lottie只是使用指定的层来遮罩视图控制器,同时尊重Z秩序。

调试

Lottie有几个调试功能需要了解。当加载动画时,不支持的功能会以其函数名记录在控制台。

如果你查看LOTHelpers.h,你会看到两个调试标志。ENABLE_DEBUG_LOGGINGENABLE_DEBUG_SHAPESENABLE_DEBUG_LOGGING增加了Lottie日志的详尽程度。它在动画过程中设置动画节点时记录日志。如果你的动画不起作用,请打开它并播放动画。控制台日志可能会给你一些线索。

ENABLE_DEBUG_SHAPES为每个层和形状的锚点绘制一个彩色的正方形。这有助于查看屏幕上是否有任何内容。

属性路径

LOTAnimationView提供了- (void)logHierarchyKeypaths,这将递归记录动画的所有可设置属性路径。这对于在运行时更改动画非常有帮助。

在运行时向动画添加视图

您不仅可以使用Lottie在运行时更改动画,还可以在运行时向LOTAnimation添加自定义UI。下面的示例展示了如何创建动态图像加载器的一些高级用法。

动态图像加载器

Spinner

上述示例显示了设置为加载旋转动画的单个LOTAnimationView。当异步下载图像时,加载旋转动画会循环动画的一部分。下载完成后,图像被添加到动画中,动画的其余部分无缝播放。画面过渡动画流畅,并调用完成块。

Spinner_Alt

现在,动画已被设计师更改,需要进行更新。只需更新包中的JSON文件即可。无需代码更改!

Spinner_Dark

在这里,设计决定为应用程序添加“深色模式”。只需几行代码即可在运行时更改动画的颜色。

是不是很强大?

查看下面的代码示例!

import UIKit
import Lottie

class ViewController: UIViewController {
  
  var animationView: LOTAnimationView = LOTAnimationView(name: "SpinnerSpin");
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    // Setup our animaiton view
    animationView.contentMode = .scaleAspectFill
    animationView.frame = CGRect(x: 20, y: 20, width: 200, height: 200)

    self.view.addSubview(animationView)
    // Lets change some of the properties of the animation
    // We arent going to use the MaskLayer, so lets just hide it
    animationView.setValue(0, forKeypath: "MaskLayer.Ellipse 1.Transform.Opacity", atFrame: 0)
    // All of the strokes and fills are white, lets make them DarkGrey
    animationView.setValue(UIColor.darkGray, forKeypath: "OuterRing.Stroke.Color", atFrame: 0)
    animationView.setValue(UIColor.darkGray, forKeypath: "InnerRing.Stroke.Color", atFrame: 0)
    animationView.setValue(UIColor.darkGray, forKeypath: "InnerRing.Fill.Color", atFrame: 0)
    
    // Lets turn looping on, since we want it to repeat while the image is 'Downloading'
    animationView.loopAnimation = true
    // Now play from 0 to 0.5 progress and loop indefinitely.
    animationView.play(fromProgress: 0, toProgress: 0.5, withCompletion: nil)
    
    // Lets simulate a download that finishes in 4 seconds.
    let dispatchTime = DispatchTime.now() + 4.0
    DispatchQueue.main.asyncAfter(deadline: dispatchTime) {
      self.simulateImageDownloaded()
    }
  }
  
  func simulateImageDownloaded() {
    // Our downloaded image
    let image = UIImage(named: "avatar.jpg")
    let imageView = UIImageView(image: image)

    // We want the image to show up centered in the animation view at 150Px150P
    // Convert that rect to the animations coordinate space
    // The origin is set to -75, -75 because the origin is centered in the animation view
    let imageRect = animationView.convert(CGRect(x: -75, y: -75, width: 150, height: 150), toLayerNamed: nil)
    
    // Setup our image view with the rect and add rounded corners
    imageView.frame = imageRect
    imageView.layer.masksToBounds = true
    imageView.layer.cornerRadius = imageRect.width / 2;
    
    // Now we set the completion block on the currently running animation
    animationView.completionBlock = { (result: Bool) in ()
      // Add the image view to the layer named "TransformLayer"
      self.animationView.addSubview(imageView, toLayerNamed: "TransformLayer", applyTransform: true)
      // Now play the last half of the animation
      self.animationView.play(fromProgress: 0.5, toProgress: 1, withCompletion: { (complete: Bool) in
        // Now the animation has finished and our image is displayed on screen
        print("Image Downloaded and Displayed")
      })
    }
    
    // Turn looping off. Once the current loop finishes the animation will stop 
    // and the completion block will be called.
    animationView.loopAnimation = false
  }
  
}

运行时更改动画

Lottie不仅可以播放漂亮的动画,还允许您在运行时更改动画。

假设我们想要创建4个切换开关。

Toggle 创建四个开关并播放它们非常简单。

let animationView = LOTAnimationView(name: "toggle");
self.view.addSubview(animationView)
animationView.frame.origin.x = 40
animationView.frame.origin.y = 20
animationView.autoReverseAnimation = true
animationView.loopAnimation = true
animationView.play()

let animationView2 = LOTAnimationView(name: "toggle");
self.view.addSubview(animationView2)
animationView2.frame.origin.x = 40
animationView2.frame.origin.y = animationView.frame.maxY + 4
animationView2.autoReverseAnimation = true
animationView2.loopAnimation = true
animationView2.play()

let animationView3 = LOTAnimationView(name: "toggle");
self.view.addSubview(animationView3)
animationView3.frame.origin.x = 40
animationView3.frame.origin.y = animationView2.frame.maxY + 4
animationView3.autoReverseAnimation = true
animationView3.loopAnimation = true
animationView3.play()

let animationView4 = LOTAnimationView(name: "toggle");
self.view.addSubview(animationView4)
animationView4.frame.origin.x = 40
animationView4.frame.origin.y = animationView3.frame.maxY + 4
animationView4.autoReverseAnimation = true
animationView4.loopAnimation = true
animationView4.play()

现在我们来更改它们的颜色

Recolored Toggle

animationView2.setValue(UIColor.green, forKeypath: "BG-On.Group 1.Fill 1.Color", atFrame: 0)
animationView3.setValue(UIColor.red, forKeypath: "BG-On.Group 1.Fill 1.Color", atFrame: 0)
animationView4.setValue(UIColor.orange, forKeypath: "BG-On.Group 1.Fill 1.Color", atFrame: 0)
[animationView2 setValue:[UIColor greenColor] forKeypath:@"BG-On.Group 1.Fill 1.Color" atFrame:@0];

keyPath是从After Effects中读取的层和属性名的点分隔路径。LOTAnimationView提供- (void)logHierarchyKeypaths,它将递归记录动画中所有可设置的关键路径。 Key Path "BG-On.Group 1.Fill 1.Color"

现在让我们更改一些属性

Multiple Colors

animationView2.setValue(UIColor.green, forKeypath: "BG-On.Group 1.Fill 1.Color", atFrame: 0)
animationView2.setValue(UIColor.red, forKeypath: "BG-Off.Group 1.Fill 1.Color", atFrame: 0)

Lottie允许您更改After Effects中任何可动画化的属性。如果没有关键帧,则会为您创建线性关键帧。如果存在关键帧,则替换其数据。

动画控制和开关

Animated Buttons

Lottie 还有一个自定义的 UIControl 子类,用于创建自定义的动画交互控制。目前 Lottie 有 LOTAnimatedSwitch,这是一个切换风格的开关控制。点击开关会播放开/关或关/开的动画并向所有目标发送一个 UIControlStateValueChanged 广播。它是以与 UISwitch 相同的方式使用,并为 Lottie 添加了一些设置动画的附加功能。

您可以使用便利方法或直接提供动画来初始化开关。

// Convenience
LOTAnimatedSwitch *toggle1 = [LOTAnimatedSwitch switchNamed:@"Switch"];
 
// Manually 
LOTComposition *comp = [LOTComposition animationNamed:@"Switch"];
LOTAnimatedSwitch *toggle1 = [[LOTAnimatedSwitch alloc] initWithFrame:CGRectZero];
[toggle1 setAnimationComp:comp];

您还可以指定动画的时间线上特定的部分用于开和关动画。默认情况下,LOTAnimatedSwitch 会为开播放动画正向,为关播放动画反向。

比如说,提供的动画从 0.5-1 进度动画开,从 0-0.5 进度动画关。

/// On animation is 0.5 to 1 progress.
[toggle1 setProgressRangeForOnState:0.5 toProgress:1];

/// Off animation is 0 to 0.5 progress.
[toggle1 setProgressRangeForOffState:0 toProgress:0.5];

此外,所有的 LOTAnimatedControls 支持更改属性以适应状态变化。这需要在 After Effects 中进行一些设置。Lottie 会根据控件状态切换可见的动画图层。这可以用来有禁用、选中或高亮状态的显示。这些状态与 After Effects 中的图层名称相关联,并且随着控件状态的变化而动态显示。

比如说我们有一个 Normally 状态和禁用 Disabled 状态的切换开关。在效果中,我们有一个包含通常的“按钮”和禁用的“Disabled”状态的前 compounded 合成。它们有不同的视觉样式。

Regular Disabled

现在在代码中,我们可以将这些 UIControlState 关联到这些图层

// Specify the layer names for different states
[statefulSwitch setLayerName:@"Button" forState:UIControlStateNormal];
[statefulSwitch setLayerName:@"Disabled" forState:UIControlStateDisabled];

// Changes visual appearance by switching animation layer to "Disabled"
statefulSwitch.enabled = NO;

// Changes visual appearance by switching animation layer to "Button"
statefulSwitch.enabled = YES;

支持的 After Effects 功能

关键帧插值


  • 线性插值
  • 贝塞尔插值
  • 保持插值
  • 跨时移动
  • 空间贝塞尔

实体


  • 变换锚点
  • 变换位置
  • 变换比例
  • 变换旋转
  • 变换不透明度

遮罩


  • 路径
  • 透明度
  • 多个遮罩(相加、相减和交集)

追踪遮罩


  • Alpha遮罩

父子级关系


  • 多个父子级关系
  • 空值

形状图层


  • 锚点
  • 位置
  • 缩放
  • 旋转
  • 透明度
  • 路径
  • 组变换(锚点,位置,缩放等)
  • 矩形(所有属性)
  • 圆形(所有属性)
  • 一个组中的多个路径
  • 偶数奇数填充规则路径
  • 反转填充规则

描边(形状图层)


  • 描边颜色
  • 描边透明度
  • 描边宽度
  • 线端形状
  • 虚线(现在动画化!)

填充(形状图层)


  • 填充颜色
  • 填充透明度

裁剪路径(形状图层)


  • 裁剪路径开始
  • 修剪路径结束
  • 修剪路径偏移

中继器


  • 支持中继器变换
  • 当前不支持偏移。

渐变


  • 支持线性渐变
  • 支持径向渐变

多星形和多边形


  • 支持!如果圆度大于100 percent,则存在一个已知的错误。

图层特性


  • 预合成
  • 图像图层
  • 形状图层
  • 空图层
  • 纯色图层
  • 父图层
  • Alpha透明图层

当前不支持After Effects功能

  • 合并形状
  • Alpha反转蒙版
  • 修剪路径的修剪形状功能
  • 表达式
  • 3D图层支持
  • 时间映射/图层倒置
  • 图层混合模式
  • 图层效果

社区贡献

备选方案

  1. 手动创建动画。在 Android 和 iOS 上手动创建动画,对于设计和工程来说是一项巨大的时间投入。通常很难,甚至无法证明如此大量的时间能够正确地完成一个动画。
  2. Facebook Keyframes。Keyframes 是 Facebook 为表情构建的一个新库。然而,Keyframes 并不支持 Lottie 的某些功能,如蒙版、遮罩、裁剪路径、虚线模式等。
  3. Gif。Gif 的大小是 bodymovin JSON 的大两倍,以固定大小渲染,无法放大以匹配大型和高密度屏幕。
  4. Png 序列。Png 序列的文件大小通常比 bodymovin JSON 的文件大小大 30-50 倍,并且也不能放大。

为什么叫 Lottie?

Lottie 以德国电影导演、剪影动画的先驱命名。她最著名的电影是《阿赫迈德王子历险记》(1926)——这是现存最古老的长篇动画电影,比华特·迪士尼的《白雪公主和七个小矮人》(1937)早了十多年 Lotte Reineger 的艺术

贡献

非常欢迎贡献者。只需上传一个带有变更描述的 PR 即可。

如果您想添加更多 JSON 文件,请随时添加!

问题或功能请求?

为任何意外损坏的功能提交 GitHub 上的 issues。如果 After Effects 文件不起作用,请将其附加到问题中。没有原始文件进行调试要困难得多。Lottie 由 Brandon Withrow 开发和维护。您可以通过电子邮件或 Twitter 联系他。

路线图(不分先后顺序)

  • 支持交互式动画过渡

lottie-ios-bb