lottie介绍及使用相关(翻译)

Overview
因为应用的下个版本的很多交互是参考Airbnb来的,而Airbnb开源了一个叫做Lottie动画库,而该库可以完成很多复杂炫酷的动画。所以在此翻译了Lottie的相应文档,熟悉其API。
通过阅读代码和Demo可以看出,Lottie是及其优秀的。它通过AE做成的动画导出JSON文件,然后前端使用Lottie直接加载JSON文件生成动画,不需要前端进行复杂的绘制等操作。同时Lottie 不仅支持iOS,还支持Mac、Android、web、React Native。而且它还具有占用内存少,加载流畅等特点,是个极其不错的第三方库。
相应文档
Lottie for iOS, macOS (and Android and React Native)
目录
- Introduction
- Installing Lottie
- iOS Sample App
- macOS Sample App
- Objective C Examples
- Swift Examples
- Debugging Lottie
- iOS View Controller Transitioning
- Changing Animations At Runtime
- Animated Controls and Switches
- Adding Subviews to Animation
- Supported After Effects Features
- Currently Unsupported After Effects Features
- Community Contributions
- Alternatives
- Why is it called Lottie?
- Contributing
- Issues or feature requests?
Introduction
Lottie是Android和iOS的移动库,用bodymovin解析Adobe After Effects导出为json的动画并在移动设备上生成矢量动画,适用于React Native!
这是第一次,设计师可以创建和发送漂亮的动画,无需程序员辛苦地手动去创建它.
由于动画由JSON驱动,因此它们的体积非常小,但复杂程度可能很高!
可以播放动画,调整大小,循环,加快速度,减慢速度,颠倒速度,甚至交互式地清理动画。
Lottie也可以播放或循环动画的一部分,可能性是无限的!
动画甚至可以 在运行时以各种方式更改 改变颜色,位置或任何关键的可变值。
Lottie也支持原生的UIViewController Transitions!
这只是Lottie能力的一小部分


<img src="https://img.haomeiwen.com/i1388397/3b2a4d25296cdabd.gif?imageMogr2/auto-orient/strip" />


Installing Lottie
Github Repo
您可以下载Lottie Github Repo和其中的Lottie.xcodeproj以构建动态或静态库。
Cocoapods
Get Cocoapods
Add the pod to your podfile
pod 'lottie-ios'
run
pod install
通过CocoaPods安装到你的项目中后,将Lottie头文件导入工程中
Objective C
#import <Lottie/Lottie.h>
Swift
import Lottie
Carthage
Get Carthage
将 Lottie 添加到 Cartfile 中
github "airbnb/lottie-ios" "master"
run
carthage update
在你的应用程序的“常规”选项卡中“链接的框架和库”,需要从Carthage / Build / iOS目录中拖放“carthage update”生成的lottie-ios.framework。
iOS Sample App
克隆这个repo,并尝试示例应用程序,
repo中包含了一个macOS示例和一个iOS示例
iOS示例应用程序演示了Lottie的几项功能



动画资源管理器允许您移除,播放,循环和调整动画大小。
可以使用内置的扫描功能从应用程序包或从Lottie文件中加载动画。
macOS Sample App
下载这个 repo 并尝试运行 the Sample App,
这个repo可以构建一个macOS示例和一个iOS示例

用于macOS的Lottie Viewer允许您拖放JSON文件用于播放,移除和循环动画。 Mac程序和iOS程序的动画代码是一样的,因此您将获得精确的Mac和iOS动画。
Objective C Examples
Lottie可以从Build中的JSON文件或URL中加载动画
如何使用JSON文件加载动画,只需将生成的JSON文件添加到xcode的工程目录下。
LOTAnimationView *animation = [LOTAnimationView animationNamed:@"Lottie"];
[self.view addSubview:animation];
[animation playWithCompletion:^(BOOL animationFinished) {
// Do Something
}];
如果你需要使用bundles中的JSON文件,加载动画
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支持iOSUIViewContentModes
的aspectFit,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 Examples
Lottie可以从Bundle中的JSON文件或URL中加载动画
如何使用JSON文件加载动画,只需将生成的JSON文件添加到xcode的工程目录中。
let animationView = LOTAnimationView(name: "LottieLogo")
self.view.addSubview(animationView)
animationView.play{ (finished) in
// Do Something
}
如果你需要使用bundles中的JSON文件,加载动画
let animationView = LOTAnimationView(name: "LottieLogo" bundle:yourBundle)
self.view.addSubview(animationView)
animationView.play()
或者你可以通过NSURL以编码的方式加载动画
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 View Controller Transitioning
Lottie带有一个UIViewController
动画控制器,用于制作自定义viewController转换!


只是成为过渡的delegate
- (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动画从一个视图控制器移动到另一个视图控制器。 它们将定位在图层的起源处。 设置为NO时,Lottie只是在指定z层时遮蔽具有指定层的视图控制器。
Debugging
Lottie有几个要了解的调试功能。
当加载动画时,不支持的功能,其工程名将打印在控制台中。
如果您查看LOTHelpers.h这个类,您将看到两个调试标志。 ENABLE_DEBUG_LOGGING
和ENABLE_DEBUG_SHAPES
。
ENABLE_DEBUG_LOGGING
增加了Lottie Logging的详细程度。 它在动画期间随时记录一个动画节点。 如果您的动画不起作用,请将其打开并播放您的动画。 控制台日志可能会给你一些关于问题什么的线索。
ENABLE_DEBUG_SHAPES
为每个图层和形状的锚点画一个彩色正方形。 这对查看屏幕上是否有任何内容很有帮助。
Keypaths
LOTAnimationView提供- (void)logHierarchyKeypaths
,它将递归记录动画的所有可设置关键路径。 这有助于在运行时更改动画。
Adding Views to an Animation at Runtime
您不仅可以(在运行时更改动画),还可以在运行时将自定义UI添加到LOTAnimation中。
下面的例子是一些进度用途的动态图像加载器。
A Dynamic Image Loading Spinner

上面的例子显示了一个单独的LOTAnimationView,它使用加载微调器动画进行设置。 加载微调器会循环一部分动画,而图像则是异步下载的。 下载完成后,图像将添加到动画中,其余动画将无缝播放。 图像完美地执行动画并被调用。

现在,动画已由设计师更改并需要更新。 所需的只是更新包中的JSON文件。 无需更改代码!

现在,动画已由设计师更改并需要更新。 所需的只是更新包中的JSON文件。 无需更改代码!
很强大吧 嗯?
查看下面的代码以获取示例!
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
}
}
Changing Animations At Runtime
Lottie可以做的不仅仅是美丽的动画。 Lottie允许您在运行时更改动画。
Say we want to create 4 toggle switches.

它很容易创建四个开关并播放它们:
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()
Now lets change their colors

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
,它将递归记录动画的所有可设置关键路径。

"BG-On.Group 1.Fill 1.Color"
Now lets change a couple of properties

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 Controls and Switches

Lottie还拥有UIControl的自定义子类,用于创建自定义动画式交互式控件。
目前Lottie有LOTAnimatedSwitch
这是一种切换式开关控制。 点击开关将播放On-Off或Off-On动画,并向所有目标发送UIControlStateValueChanged广播。 它跟UISwitch使用方式相同,同时使用Lottie设置了一些动画。
您可以使用conveneince方法或直接提供动画来初始化开关。
// 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中的图层名称关联,并在控件更改状态时动态显示。
可以说我们有一个正常和禁用状态的切换开关。 在效果中,我们有一个包含常规“按钮”和禁用“禁用”状态的Precomps的组合。 他们有不同的视觉风格。


现在在代码中,我们可以将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;
Supported After Effects Features
Keyframe Interpolation
- Linear Interpolation
- Bezier Interpolation
- Hold Interpolation
- Rove Across Time
- Spatial Bezier
Solids
- Transform Anchor Point
- Transform Position
- Transform Scale
- Transform Rotation
- Transform Opacity
Masks
- Path
- Opacity
- Multiple Masks (additive, subtractive and intersection)
Track Mattes
- Alpha Matte
Parenting
- Multiple Parenting
- Nulls
Shape Layers
- Anchor Point
- Position
- Scale
- Rotation
- Opacity
- Path
- Group Transforms (Anchor point, position, scale etc)
- Rectangle (All properties)
- Eclipse (All properties)(Eclipse
- Multiple paths in one group
- Even-Odd winding paths
- Reverse Fill Rule
Stroke (shape layer)
- Stroke Color
- Stroke Opacity
- Stroke Width
- Line Cap
- Dashes (Now Animated!)
Fill (shape layer)
- Fill Color
- Fill Opacity
Trim Paths (shape layer)
- Trim Paths Start
- Trim Paths End
- Trim Paths Offset
Repeaters
- Supports repeater transforms
- Offset currently not supported.
Gradients
- Support for Linear Gradients
- Support for Radial Gradients
Polystar and Polygon
- Supported! Theres a known bug if the roundness is greater than 100 percent.
Layer Features
- Precomps
- Image Layers
- Shape Layers
- Null Layers
- Solid Layers
- Parenting Layers
- Alpha Matte Layers
Currently Unsupported After Effects Features
- Merge Shapes
- Alpha Inverted Masks
- Trim Shapes Individually feature of Trim Paths
- Expressions
- 3d Layer support
- Time remapping / Layer Reverse
- Layer Blend Modes
- Layer Effects
Community Contributions
- Xamarin bindings
- NativeScript bindings
- Appcelerator Titanium bindings
- macOS Support added by Alex Pawlowski
Alternatives
- 手动构建动画。 手动构建动画是跨Android和iOS设计和工程的时间承诺。 通常很难甚至不可能证明花费这么多时间来获得动画是正确的。
- [Facebook关键帧](https://github.com/facebookincubator/Keyframes)。 关键帧是来自Facebook的精彩新图书馆,它们为反应而构建。 但是,关键帧不支持Lottie的一些功能,如遮罩,遮罩,修剪路径,破折号图案等。
- Gifs。 GIF的尺寸是bodymovin JSON尺寸的两倍多,并且以固定的尺寸渲染,无法放大以匹配大屏幕和高密度屏幕。
- Png序列。 Png序列比gifs更糟,因为它们的文件大小通常是bodymovin json大小的30-50倍,也不能放大。
Why is it called Lottie?
Lottie(洛蒂)是以德国电影导演和剪影动画的先驱者命名的。 她最着名的电影是“阿彻梅德王子历险记”(1926年) - 这是迄今为止最古老的长篇动画电影,在沃尔特迪斯尼的长篇白雪公主和七个小矮人(1937)之前超过十年
The art of Lotte Reineger
Contributing
贡献者非常欢迎。 只需上传一份描述您所做更改的公关。
如果你想添加更多的JSON文件,请随时这样做!
Issues or feature requests?
文件github问题的任何意外中断。 如果After Effects文件无效,请将其附加到您的问题中。 在没有原始文件的情况下进行调试要困难得多。 Lottie由[Brandon Withrow]开发和维护(mailto:brandon.withrow@airbnb.com)。 请随时通过电子邮件或[Twitter](https://twitter.com/theWithra)
Roadmap (In no particular order)
- 添加对交互式动画过渡的支持