diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..a1e5821 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +open_collective: lottie diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE new file mode 100644 index 0000000..a9d80b5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE @@ -0,0 +1,6 @@ +This repo is NOT for reporting issues on the individual libraries. +If you are looking for them, view the README for links to the individual libraries. + +This repo is for the docs at https://airbnb.io/lottie. Proposing changes to the docs is ridiculously easy. Please follow the directions on the README. You don't even need to know git or use a terminal to update the docs. You can do it right from your browser. + +Issues reported here are not checked regularly and will probably not get you very far. \ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..eaffbb3 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +lottie.airbnb.tech \ No newline at end of file diff --git a/README.md b/README.md index 1d670be..9157dd6 100644 --- a/README.md +++ b/README.md @@ -1,115 +1,37 @@ -# Lottie for [Android](https://github.com/airbnb/lottie-android), [iOS](https://github.com/airbnb/lottie-ios), [Web](https://github.com/airbnb/lottie-web), [React Native](https://github.com/airbnb/lottie-react-native), and [Windows](https://aka.ms/lottie) - - - - - - -
- Get it on Google Play - - English badge -
- - -Lottie is a library for Android, iOS, Web, and Windows that parses [Adobe After Effects](http://www.adobe.com/products/aftereffects.html) animations exported as json with [Bodymovin](https://github.com/airbnb/lottie-web) and renders them natively on mobile and on the web! - -For the first time, designers can create **and ship** beautiful animations without an engineer painstakingly recreating it by hand. They say a picture is worth 1,000 words so here are 13,000: - -![Lottie Logo animation](images/Introduction_00_sm.gif) - -![Example1](images/Introduction_01_sm.gif) - - -![Example2](images/Introduction_02_sm.gif) - - -![Example3](images/Introduction_03_sm.gif) - - -![Example4](images/Introduction_04_sm.gif) - - -All of these animations were created in After Effects, exported with Bodymovin, and rendered natively with no additional engineering effort. - -[Bodymovin](https://github.com/airbnb/lottie-web) is an After Effects plugin created by Hernan Torrisi that exports After effects files as json and includes a javascript web player. We've built on top of his great work to extend its usage to Android, iOS, React Native, and Windows. - -Read more about it on our [blog post](http://airbnb.design/introducing-lottie/) -Or get in touch on GitHub or via lottie@airbnb.com - -## Other Platforms - * [Xamarin (martijn00)](https://github.com/martijn00/LottieXamarin) - * [NativeScript (bradmartin)](https://github.com/bradmartin/nativescript-lottie) - * [Axway Appcelerator (m1ga)](https://github.com/m1ga/ti.animation) - * [ReactXP (colmbrady)](https://github.com/colmbrady/lottie-reactxp) - * [Flutter (simolus3)](https://github.com/simolus3/fluttie) - * [Flutter (fabiomsr)](https://github.com/fabiomsr/lottie-flutter) - -## Sample App - -You can build the sample app for Android yourself or download it from the [Play Store](https://play.google.com/store/apps/details?id=com.airbnb.lottie). The sample app includes some built in animations but also allows you to load an animation from internal storage or from a url. - -For Windows, you can get the [Lottie Viewer app](https://aka.ms/lottieviewer) to preview Lottie animation and codegen classes, and the [Lottie Samples app](https://aka.ms/lottiesamples) to get started with code samples and simple tutorials. - -## Shipping something with Lottie? - -Email us at [lottie@airbnb.com](lottie@airbnb.com) and soon we will create a testimonals and use cases page with real world usages of Lottie from around the world. -We also have an internal regression testing repo that we can use to prevent causing regressions with your animations. - -## Alternatives -1. Build animations by hand. Building animations by hand is a huge time commitment for design and engineering across Android and iOS. It's often hard or even impossible to justify spending so much time to get an animation right. -2. [Facebook Keyframes](https://github.com/facebookincubator/Keyframes). Keyframes is a wonderful new library from Facebook that they built for reactions. However, Keyframes doesn't support some of Lottie's features such as masks, mattes, trim paths, dash patterns, and more. -2. Gifs. Gifs are more than double the size of a bodymovin JSON and are rendered at a fixed size that can't be scaled up to match large and high density screens. -3. Png sequences. Png sequences are even worse than gifs in that their file sizes are often 30-50x the size of the bodymovin json and also can't be scaled up. -4. Animated Vector Drawable (Android only). More performant because it runs on the RenderThread instead of the main thread. Supports only a subset of Lottie features. Progress can't be manually set. Doesn't support text or dynamic colors. Can't be loaded programatically or over the internet. - -## Why is it called Lottie? -Lottie is named after a German film director and the foremost pioneer of silhouette animation. Her best known films are The Adventures of Prince Achmed (1926) โ€“ the oldest surviving feature-length animated film, preceding Walt Disney's feature-length Snow White and the Seven Dwarfs (1937) by over ten years -[The art of Lotte Reineger](https://www.youtube.com/watch?v=LvU55CUw5Ck&feature=youtu.be) - -## Contributing -Contributors are more than welcome. Just upload a PR with a description of your changes. - -If you would like to add more JSON files feel free to do so! - -## Issues or feature requests? -File github issues for anything that is unexpectedly broken. If an After Effects file is not working, please attach it to your issue. Debugging without the original file is much more difficult. - -## Articles, Interviews & Podcasts - -Here are some articles and podcasts from the Lottie team @ Airbnb - -[Behind the scenes: Why we built Lottie, our new open-source animation tool here.](https://airbnb.design/introducing-lottie/) - -[Dig into the details and back story with Brandon Withrow and Salih Abdul-Karim on the School of motion podcast](https://www.schoolofmotion.com/blog/after-effects-to-code-lottie-from-airbnb) - -[Learn more about Lottie from Gabriel Peal on the Fragmented Podcast](http://fragmentedpodcast.com/episodes/82/) - -[Lottie Animation with Brandon Withrow and Gabriel Peal on Software engineering daily podcast](https://softwareengineeringdaily.com/2017/08/10/lottie-animation-with-brandon-withrow-and-gabriel-peal/) - - -## Community articles and videos - -Heres some links from around the community - -[A Lottie to Like](https://t.co/dadjvgv9vk) by Nick Butcher - -[Creating better user experiences with animations and Lottie](https://pspdfkit.com/blog/2017/creating-better-user-experiences-with-animations-and-lottie/)by Samo Korosec and Stefan Keileithner - -[How to use Lottie \(In Chinese\)](https://goo.gl/e7BkND) by PattyDraw - -[A Beginningโ€™s Guide to Lottie: Creating Amazing Animations in iOS Apps](https://www.appcoda.com/lottie-beginner-guide/#) by Simon NG - -[Take your animations to the next level with Airbnb framework, Lottie](https://medium.com/@jamesrochabrun/take-your-animations-to-the-next-level-with-airbnb-framework-lottie-ab6c6152acba) by James Rochabrun - -[iOS Swift Tutorial: Animations with After Effects and Lottie](https://www.youtube.com/watch?v=ESjFEaZx7UI) by Brian Advent - -[iOS Swift Tutorial: Interactive Animations with After Effects and Lottie](https://www.youtube.com/watch?v=QyL-jp9bFdM) by Brian Advent - -[After Effects for wiOS Developers: Dynamic Content in Animations](https://youtu.be/2HhgLir6Jz0?list=PLUDTy1CWIw-qu2EuzNVFQawyW5jmC5W7G) by Brian Advent - -[Creating cool animations in android using Lottie](https://www.youtube.com/watch?v=T4v72xJqNpQ)[Chetan Sachdeva](https://www.youtube.com/channel/UC_4TBWZcI-tdZ02wESTRVNw) by Chetan Sachdeva - -[Boost Your User Experience with Lottie for React Native](https://blog.reactnativecoach.com/boost-your-user-experience-with-lottie-for-react-native-5da1ac589982) by Samuli Hakoniemi - -[How to use 'Lottie' in Framer X](https://blog.reactnativecoach.com/boost-your-user-experience-with-lottie-for-react-native-5da1ac589982) by ruucm +# Lottie Documentation + +This repo is the home of the unified Lottie docs hosted at [http://airbnb.io/lottie](http://airbnb.io/lottie). This repo is NOT the place to contribute to or report issues on any of the players or the After Effects plugin. + + +## Contributing to the docs directly on GitHub (easy) +Because the Lottie docs are created directly from the markdown in this repo, you can use the GitHub web editor to edit and propose changes to the docs directly from your browser without any knowledge of git. +To do that, find the markdown file with the docs you want to edit and follow [GitHub's instructions](https://docs.github.com/en/free-pro-team@latest/github/managing-files-in-a-repository/editing-files-in-another-users-repository) to edit and propose changes to a markdown file. Once approved, the docs will be updated immediately. + +## Contributing to the docs by forking this repo (still pretty easy) +[http://airbnb.io/lottie](http://airbnb.io/lottie) runs on [docsify](https://docsify.js.org/#/?id=docsify). Docsify was chosen because it takes hosted markdown and generates the page dynamically. That means that simply updating the markdown files here is all that is needed to update [http://airbnb.io/lottie](http://airbnb.io/lottie). + +1. Fork and clone this repo. +1. Install docsify: `sudo npm install -g docsify-cli`. +1. Startup the local docsify server with `docsify serve .` from the root of this repo. +1. Edit the markdown and verify your changes on the localhost url outputted from the `docsify serve` command. +1. Put up a pull request to this repo and tag `@gpeal` +1. Enjoy the updated docs! + +# Looking for the libraries? +## Official Libraries +* [Android](https://github.com/airbnb/lottie-android/) +* [iOS](https://github.com/airbnb/lottie-ios/) +* [Web](https://github.com/airbnb/lottie-web/) +* [After Effects Plugin](https://github.com/airbnb/lottie-web/) + +## Unofficial Libraries +* [React Native](https://github.com/lottie-react-native/lottie-react-native) +* [Windows](https://github.com/windows-toolkit/Lottie-Windows) +* [Qt](https://blog.qt.io/blog/2019/03/08/announcing-qtlottie/) +* [Skia](https://skia.org/user/modules/skottie) +* [Xamarin](https://github.com/martijn00/LottieXamarin) +* [NativeScript](https://github.com/bradmartin/nativescript-lottie) +* [Titanium SDK](https://github.com/m1ga/ti.animation) +* [Qt QML](https://sea-region.github.com/kbroulik/lottie-qml) +* [Rlottie](https://github.com/Samsung/rlottie) +* [Python](https://gitlab.com/mattia.basaglia/python-lottie) diff --git a/_sidebar.md b/_sidebar.md index 519288a..491e348 100644 --- a/_sidebar.md +++ b/_sidebar.md @@ -1,11 +1,13 @@ * [**Home**](/README.md) +* [**Sponsorship**](/sponsorship.md) * [**Supported After Effects Features**](/supported-features.md) * [**Community Showcase**](/community-showcase.md) +* [**After Effects**](/after-effects.md) * [**Android**](/android.md) -* [**iOS/MacOS**](ios.md) +* [**Android - Jetpack Compose**](/android-compose.md) +* [**iOS**](/ios.md) * [**React Native**](/react-native.md) * [**Web**](/web.md) * [**Windows**](/windows.md) -* [**After Effects**](/after-effects.md) * [**Contribute to Docs**](/docs.md) * [**Other Platforms**](/other-platforms.md) diff --git a/after-effects.md b/after-effects.md index 970f316..402c143 100644 --- a/after-effects.md +++ b/after-effects.md @@ -2,9 +2,13 @@ Get up and running creating animations for Lottie in After Effects! +[Bodymovin](https://github.com/airbnb/lottie-web) is an After Effects plugin created by Hernan Torrisi that exports After effects files as json and includes a javascript web player. We've built on top of his great work to extend its usage to Android, iOS, React Native, and Windows. + +[LottieFiles for After Effects](https://lottiefiles.com/plugins/after-effects) is a plugin created by LottieFiles, lets you render your animation natively but also offers additional features such as testing on mobile and a render graph that lets you check your animations CPU usage as you create your Lottie. You can access a library of 1000s of free animations with their AEP file on LottieFiles straight from within the plugin itself too. + # Installing Bodymovin -### 1 - Close After Effects if its open +### 1 - Close After Effects if it's open ### 2 - Install the ZXP installer @@ -95,7 +99,7 @@ Using alpha mattes can impact performance. If you're using an alpha matte or an ## Debugging -If an animation is broken. Try debugging the animation by exporting only certain layers at a time to see which ones work and which ones don't. After you isolate the problem areas, be sure to file a github issue with the After effects file attached and then you can choose to remake those layers in a different way. +If an animation is broken. Try debugging the animation by exporting only certain layers at a time to see which ones work and which ones don't. After you isolate the problem areas, be sure to file a GitHub issue with the After effects file attached and then you can choose to remake those layers in a different way. ## No Blending modes or Luma mattes @@ -123,7 +127,7 @@ This walkthrough explains how to get artwork from Sketch to Lottie. If you alrea It doesn't dive into any animation techniques. For that check out one of our other walkthroughs. -We're assuming you have three things. Adobe Illustrator, Adobe After Effects, and [Bodymovin](https://github.com/airbnb/lottie-web). For a walkthrough on how to install Bodymovin go [here](/bodymovin-installation.md). +We're assuming you have three things. Adobe Illustrator, Adobe After Effects, and [Bodymovin](https://github.com/airbnb/lottie-web). For a walkthrough on how to install Bodymovin go [here](#Installing%20Bodymovin). ### 1 - Ensure artwork is grouped @@ -134,7 +138,7 @@ To get the asset exported in one piece everything needs to be put into a single ### 2 - Select the group and export as an SVG -You might be thinking ๐Ÿค” Why not export artwork as a PDF or EPS that goes directly into AE?? We'll explain why later. If you don't have illustrator a PDF or EPS will still work, you just might have to do more cleanup in After Effects. Check out cleanup tips in the [Debugging section](/after-effects/debugging.md) +You might be thinking ๐Ÿค” Why not export artwork as a PDF or EPS that goes directly into AE?? We'll explain why later. If you don't have illustrator a PDF or EPS will still work, you just might have to do more cleanup in After Effects. Check out cleanup tips in the [Debugging section](#debugging) ![ArtworkWalkthrough_02](/images/ArtworkWalkthrough_02.png) @@ -224,7 +228,7 @@ After its downloaded just use the camera to scan the QR code. If you're animation looks correct in the preview app, you are good to go! -If it doesn't then its time to do some debugging. Check out our [After Effects debugging tips](/after-effects/debugging.md) to see some techniques to get your animation working. If all else fails file an issue on github in the respective repo ([iOS](http://www.github.com/airbnb/lottie-ios), [Android](http://www.github.com/airbnb/lottie-android)) with your AE file attached and we'll do our best to support you. +If it doesn't then its time to do some debugging. Check out our [After Effects debugging tips](/after-effects/debugging.md) to see some techniques to get your animation working. If all else fails file an issue on GitHub in the respective repo ([iOS](http://www.github.com/airbnb/lottie-ios), [Android](http://www.github.com/airbnb/lottie-android)) with your AE file attached and we'll do our best to support you. # Advanced Illustrator to Lottie workflow @@ -265,4 +269,4 @@ Coming soon... ## Animation easings are off -Coming soon... \ No newline at end of file +Coming soon... diff --git a/android-compose.md b/android-compose.md new file mode 100644 index 0000000..6cafac7 --- /dev/null +++ b/android-compose.md @@ -0,0 +1,199 @@ +# Getting Started +Add the dependency to your project `build.gradle` file: + +
dependencies {
+    ...
+    implementation "com.airbnb.android:lottie-compose:$lottieVersion"
+    ...
+}
+
+The latest stable version is: ![lottieVersion](https://maven-badges.herokuapp.com/maven-central/com.airbnb.android/lottie-compose/badge.svg) + +Snapshots are hosted on Sonatype. First, add the Sonatype repository to your `build.gradle` file: + +```groovy +allprojects { + repositories { + ... + maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } + } +} +``` + +The latest snapshot version is: ![lottieSnapshotVersion](https://img.shields.io/nexus/s/com.airbnb.android/lottie-compose?server=https%3A%2F%2Foss.sonatype.org) + +# Basic Usage +```kotlin +@Composable +fun Loader() { + val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.loading)) + val progress by animateLottieCompositionAsState(composition) + LottieAnimation( + composition = composition, + progress = { progress }, + ) +} +``` +Or with the `LottieAnimation` overload that merges `LottieAnimation` and `animateLottieCompositionsState()` +```kotlin +@Composable +fun Loader() { + val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.loading)) + LottieAnimation(composition) +} +``` + +# LottieComposition +`LottieComposition` is the parsed version of your Lottie json file. It is stateless and can be cached/reused freely. +To create a `LottieComposition`: +* Use `rememberLottieComposition(spec)` +* Pass in a `LottieCompositionSpec`. `LottieCompositionSpec` is a sealed class that lets you select the source (res/raw, assets, string, network, etc.). + +For example: +```kotlin +val composition1 by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.animation)) +val composition2 by rememberLottieComposition(LottieCompositionSpec.Url("https://...")) +// src/main/assets/animations/animation.json +val composition3 by rememberLottieComposition(LottieCompositionSpec.Asset("animations/animation.json")) +``` + +The type returned from `rememberLottieComposition(spec)` is +```kotlin +interface LottieCompositionResult : State +``` +This allows you to use it in two ways: +```kotlin +val composition: LottieComposition? by rememberLottieComposition(spec) +``` +This will return null until the composition is parsed and then will return the `LottieComposition` object. +Use this version in most cases, especially if you don't need any of the extra functionality on `LottieCompositionResult`. + +```kotlin +val compositionResult: LottieCompositionResult = rememberLottieComposition(spec) +``` +`LottieCompositionResult` lets you: +1. Access the composition via `compositionResult.value` +2. Access `error`, `isLoading`, `isComplete`, `isFailure`, and `isSuccess` properties. +3. Call `await()` to await the parsed composition from a coroutine. + +### Retries +In most cases, you shouldn't expect parsing to fail. However, if you are loading an animation from the network or loading an animation from a file without the correct permissions, it may fail. To handle failures and retries: +```kotlin +val retrySignal = rememberLottieRetrySignal() +val composition by rememberLottieComposition( + LottieCompositionSpec.Url("not a url"), + onRetry = { failCount, exception -> + retrySignal.awaitRetry() + // Continue retrying. Return false to stop trying. + true + } +) +``` +Then, you can call `retrySignal.retry()` from something like a click listener to retry loading. + +# LottieAnimation Composable +`LottieAnimation` is the primary Lottie composable. It's parameters include: +1. The `LottieComposition` that should be rendered (or null if it hasn't been loaded or parsed yet). +1. The progress that should be rendered. Driving the animation progress is decoupled from the composable so that you can either use Lottie's animation utilities or create your own based on other animation sources or app state like download progress or gestures. +3. Render settings such as speed, dynamic properties, images, render mode (hardware or software), etc. + +# Animating/Updating Progress + +You have the option of handling progress entirely yourself. If you choose to do that, just pass in `progress` to your `LottieAnimation` composable. + +In most cases, you will want to use either `animateLottieCompositionAsState()` or `LottieAnimatable`. These APIs were designed to be analogous to the standard Jetpack Compose APIs. `animateLottieCompositionAsState` is analogous to [animate*AsState](https://developer.android.com/jetpack/compose/animation#animatable) and `LottieAnimatable` is analogous to [Animatable](https://developer.android.com/jetpack/compose/animation#animatable). + +The decision for whether to use one over the other is similar as well: +* If your animation is very simple or a function of other state properties, use `animateLottieCompositionAsState()`. +* If you need to imperatively call `animate` or `snapTo` from something like a `LaunchedEffect` then use `LottieAnimatable`. + +`animateLottieCompositionAsState()` returns and `LottieAnimatable` implements: +```kotlin +interface LottieAnimationState : State +``` + +### animateLottieCompositionAsState() +```kotlin +val progress by animateLottieCompositionAsState(composition) +``` +```kotlin +val progress by animateLottieCompositionAsState( + composition, + iterations = LottieConstants.IterateForever, +) +``` +```kotlin +val progress by animateLottieCompositionAsState( + composition, + clipSpec = LottieClipSpec.Progress(0.5f, 0.75f), +) +``` + +### LottieAnimation overload +There is an overloaded version of the `LottieAnimation` composable that merges the `LottieAnimation` and `animateLottieCompositionAsState` parameters. +```kotlin +LottieAnimation( + composition, + iterations = LottieConstants.IterateForever, + clipSpec = LottieClipSpec.Progress(0.5f, 0.75f), +) +``` + +### LottieAnimatable +```kotlin +@Stable +class MyHoistedState { + val lottieAnimatable = LottieAnimatable() + val somethingElse by mutableStateOf(0f) +} +``` +```kotlin +val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.animation)) +val lottieAnimatable = rememberLottieAnimatable() +LaunchedEffect(Unit) { + lottieAnimatable.animate( + composition, + iterations = LottieConstants.IterateForever, + clipSpec = LottieClipSpec.Progress(0.5f, 0.75f), + ) +} +``` + +# Images + +Images should be avoided whenever possible. They are much larger, less performant, and can lead to pixelation. Whenever possible, try and make your animation consist solely of vectors. However, Lottie does support images in one of 4 ways: +1. Baked into the Lottie json file. This is done via an option in the exporter (such as the Bodymovin After Effects plugin). When done, images are encoded as a base64 string and embedded directly in the json file. This is the simplest way to use images because everything is contained in a single file and no additional work is necessary to make them work. +1. Zipped with the json file in a single zip file. When parsing the animation, Lottie will unzip the animation and automatically link any images in zip file to the composition. These zip files can be stored in `src/main/assets` and loaded via `LottieCompositionSpec.Asset` or downloaded via the internet and loaded via `LottieCompositionSpec.Url`. +1. Stored in `src/main/assets/*`. When the animation is exported, it may include references to external images referenced via their file name. When this method is used, the images should be stored in a subdirectory within your assets folder and set via the `imageAssetsFolder` parameter on your `LottieAnimation` composable. +1. Via `LottieProperty.IMAGE` dynamic properties. + +# Dynamic Properties + +Lottie allows you to update Lottie animation properties at runtime. Some reasons you may want to do this are: +1. Change colors for day/night or other app theme. +2. Change the progress of a specific layer to show download progress. +3. Change the size and position of something in response to a gesture. + +To use dynamic properties, you need 3 things: +1. a `LottieProperty`. These are static constants that represent what you are trying to change. The type of the property represents the type that you will return to Lottie to update its value. For example, `LottieProperty.OPACITY` is an `Integer` and accepts values 0-100. +1. A `KeyPath`. A KeyPath is a path to the animation node that has the property that you want to animate. Refer to the docs for `KeyPath` on how to construct one. +1. A `LottieValueCallback` that will get called on each frame or a single value that will be returned on every frame until you update it. + +You use those three to construct a `LottieDynamicProperties` object like this: +```kotlin +val dynamicProperties = rememberLottieDynamicProperties( + rememberLottieDynamicProperty( + property = LottieProperty.COLOR, + value = color.toArgb(), + keyPath = arrayOf( + "H2", + "Shape 1", + "Fill 1", + ) + ), +) +``` +and pass it as a parameter to your `LottieAnimation` composable. + +You can chain together multiple dynamic properties if you want to update several at the same time. This example changes the heart color of [heart.json](https://raw.githubusercontent.com/airbnb/lottie-android/master/sample/src/main/res/raw/heart.json) and can also be seen in [these examples](https://github.com/airbnb/lottie-android/blob/master/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/examples/DynamicPropertiesExamplesPage.kt). + diff --git a/android.md b/android.md index 8f7ce83..fcedadf 100644 --- a/android.md +++ b/android.md @@ -1,5 +1,5 @@ # Getting Started -Gradle is the only supported build configuration, so just add the dependency to your project `build.gradle` file: +Add the dependency to your project `build.gradle` file:
dependencies {
     ...
@@ -15,25 +15,28 @@ You can build the sample app yourself or download it from the [Play Store](https
 
Get it on Google Play - +--- # Core Classes * `LottieAnimationView` extends ImageView and is the default and simplest way to load a Lottie animation. * `LottieDrawable` has most of the same APIs as LottieAnimationView but you can use it on any View you want. -* `LottieComposition` is the stateless model repesentation of an animation. You can create one with LottieCompositionFactory and set it on a LottieDrawable or LottieAnimationView. +* `LottieComposition` is the stateless model representation of an animation. This file is safe to cache for as long as you need and can be freely reused across drawables/views. +* `LottieCompositionFactory` allows you to create a LottieComposition from a number of inputs. This is what the `setAnimation(...)` APIs on `LottieDrawable` and `LottieAnimationView` use under the hood. The factory methods share the same cache with those classes as well. +--- # Loading an Animation -Lottie supports API 16 and above. +Lottie can load animations from: -Lottie animations can load animations from: * A json animation in `src/main/res/raw`. * A json file in `src/main/assets`. * A zip file in `src/main/assets`. See [images docs](/android?id=images) for more info. +* A [dotLottie](https://dotlottie.io/) file in `src/main/assets`. * A url to a json or zip file. * A json string. The source can be from anything including your own network stack. * An InputStream to either a json file or a zip file. + ### From XML The simplest way to use it is with LottieAnimationView: @@ -58,82 +61,74 @@ It is recommended to use `lottie_rawRes` because you can use static references t ### Programmatically -You can also call many Lottie APIs on LottieAnimationView directly. View the class reference for the full set of APIs. +`LottieAnimationView`, `LottieDrawable`, and `LottieCompositionFactory` each has methods for the corresponding locations. + +Note: to correctly load dark mode (`-night`) resources, make sure you pass `Activity` as a context where possible (instead of e.g. the application context). The `Activity` won't be leaked. ### Caching Animations All Lottie animations are cached with a LRU cache by default. Default cache keys will be created for animations loaded from `res/raw/` or `assets/`. Other APIs require setting a cache key. -If you fire multiple animation requests for the same animation in parallel such as a wishlist heart in a RecyclerView, subsequent requests will join the existing task so it only gets parsed once (Lottie >= 2.6.0). - -# Replacing a static asset with Lottie -One of the primary motivations behind Lottie is to make shipping animations just as easy as shipping static assets. +If you fire multiple animation requests for the same animation in parallel such as a wishlist heart in a RecyclerView, subsequent requests will join the existing task so it only gets parsed once. -## Switch from static assets to animations with 3 lines of code! +--- +# Global Configuration +Lottie has some global configuration options. None are required by default but it can be used to: +* Use your own network stack instead of Lottie's built in one when loading animations from the network. +* Provide your own cache directories for animation fetched from the network instead of using Lottie's default one (`cacheDir/lottie_network_cache`). +* Enable systrace makers for debugging. +* Disable Lottie's network cache completely if you want to implement custom network fetcher-level caching strategy. -### Static Asset Workflow -Put your pngs or vector drawables (xml) in `res/drawable` -Include it in your layout -```xml - -``` - -### Lottie workflow - -Put your lottie json in `res/raw` -Include it in your layout: -```xml - +To set it up, somewhere during your application initialization, include: +```kotlin +Lottie.initialize( + LottieConfig.Builder() + .setEnableSystraceMarkers(true) + .setNetworkFetcher(...) + .setNetworkCacheDir(...) + .setEnableNetworkCache(false) +) ``` -`LottieAnimationView` extends `ImageView` so you can start by simply replacing your ImageViews with LottieAnimationViews even if you are still using drawables! - +--- # Animation Listeners You can control the animation or add listeners: -```java -animationView.addAnimatorUpdateListener((animation) -> { - // Do something. -}); -animationView.playAnimation(); -... -if (animationView.isAnimating()) { - // Do something. +```kotlin +animationView.addAnimatorUpdateListener { animation -> +} +animationView.addAnimatorListener(...) +animationView.addPauseListener { } -... -animationView.setProgress(0.5f); -... + ``` In the update listener callback: -`animation.getAnimatedValue()` will return the progres of the animation regardless of the currently set min/max frame [0,1]. +`animation.getAnimatedValue()` will return the progress of the animation regardless of the currently set min/max frame [0,1]. `animation.getAnimatedFraction()` will return the progress of the animation taking into account the set min/max frame [minFrame,maxFrame]. +### Failure Listener + +Set a default failure listener that will be called if any of the setAnimation APIs fail for any reason. This can be used to replace the default behavior. The default behavior will log any network errors and rethrow all other exceptions. + +If you are loading an animation from the network, errors may occur if your user has no internet. You can use this listener to retry the download or you can have it default to an error drawable with `setFallbackResource(int)`. Unless you are using `setAnimationFromUrl(String)`, errors are unexpected. + +Set the listener to `null` to revert to the default behavior. + ### Custom animators Although `playAnimation()` is sufficient for the vast majority of use cases, you can call `setProgress(...)` in the update callback for your own animator. This can be useful to tie an animation to something like a gesture, download progress, or scroll position. -```java +```kotlin // Custom animation speed or duration. -ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f); -animator.addUpdateListener(animation -> { - animationView.setProgress(animation.getAnimatedValue()); -}); -animator.start(); +val animator = ValueAnimator.ofFloat(0f, 1f) +animator.addUpdateListener { + animationView.setProgress(animation.animatedValue) +} +animator.start() ``` +--- # Looping Lottie support advanced looping functionality that mirrors `ValueAnimator`. As such, you can call `setRepeatMode(...)` or `setRepeatCount(...)` as you would on a `ValueAnimator` @@ -141,22 +136,14 @@ You can also enable looping from xml with `lottie_loop="true"` You can loop a specific part of an animation by using `setMinFrame`, `setMaxFrame`, or `setMinAndMaxFrame`. There are multiple versions of each that take frame, progress (from 0.0 to 1.0) or a marker name (specified in After Effects). +--- # Animation Size (px vs dp) _**Lottie converts all px values in After Effects to dps**_ on device so that everything is rendered at the same size across devices. This means that instead of making an animation in After Effects that is 1920x1080, it should be more like 411x731px in After Effects which roughly corresponds to the dp screen size of most phones today. However, if your animation isn't the perfect size, you have two options: -# ImageView scaleType - -LottieAnimationView is a wrapped `ImageView` and it supports `centerCrop` and `centerInside` so you may use those two as you would with any other image. - -## Scaling Up/Down - -`LottieAnimationView` and `LottieDrawable` both have a `setScale(float)` API that you can use to manually scale up or down your animation. This is rarely useful but can be in certain situations. - -If your animation is performing slowly, make sure to check the documentation on [performance](/android/performance.md). However, try scaling your animation down in combination with a scaleType. This will reduce the amount that Lottie renders per frame. This is particularly helpful if you have large mattes or masks. - +--- # Dynamic Properties You can update properties dynamically at runtime. This can be used for a variety of purposes such as: @@ -165,17 +152,17 @@ You can update properties dynamically at runtime. This can be used for a variety * Animating a single part of an animation in response to an event. * Responding to view sizes or other values not known at design time. -## Understanding After Effects +### Understanding After Effects To understand how to change animation properties in Lottie, you should first understand how animation properties are stored in Lottie. -Animation properties are stored in a data tree that mimics the information heirarchy of After Effects. In After Effects a `Composition` is a collection of `Layers` that each have their own timelines. `Layer` objects have string names, and their contents can be an image, shape layers, fills, strokes, or just about anything that is drawable. Each object in After Effects has a name. Lottie can find these objects and properties by their name using a `KeyPath`. +Animation properties are stored in a data tree that mimics the information hierarchy of After Effects. In After Effects a `Composition` is a collection of `Layers` that each have their own timelines. `Layer` objects have string names, and their contents can be an image, shape layers, fills, strokes, or just about anything that is drawable. Each object in After Effects has a name. Lottie can find these objects and properties by their name using a `KeyPath`. -## Usage +### Usage To update a property at runtime, you need 3 things: 1. KeyPath 1. LottieProperty 1. LottieValueCallback -### KeyPath +#### KeyPath A KeyPath is used to target a specific content or a set of contents that will be updated. A KeyPath is specified by a list of strings that correspond to the hierarchy of After Effects contents in the original animation. KeyPaths can include the specific name of the contents or wildcards: @@ -184,15 +171,15 @@ KeyPaths can include the specific name of the contents or wildcards: * **Globstar** `**` * Globstars match zero or more layers. -### KeyPath resolution +#### KeyPath resolution KeyPaths have the ability to store an internal reference to the content that they resolve to. When you create a new KeyPath object, it will be unresolved. LottieDrawable and LottieAnimationView has a `resolveKeyPath()` method that takes a KeyPath and returns a list of zero or more resolved KeyPaths that each resolve to a single piece of content and are internally resolved. This can be used to discover the structure of your animation if you don't know it. To do so, in a development environment, resolve `new KeyPath("**")` and log the returned list. However, you shouldn't use `**` by itself with a ValueCallback because it will be applied to every single piece of content in your animation. If you resolve your KeyPaths and want to subsequently add a value callback, use the KeyPaths returned from that method because they will be internally resolved and won't have to do a tree walk to find the content again. See the documentation for `KeyPath` for more information. -### LottieProperty +#### LottieProperty LottieProperty is an enumeration of properties that can be set. They correspond to the animatable value in After Effects and the available properties are listed above and in the documentation for `LottieProperty` -### ValueCallback +#### ValueCallback The ValueCallback is what gets called every time the animation is rendered. The callback provides: 1. Start frame of the current keyframe. 1. End frame of the current keyframe. @@ -204,131 +191,51 @@ The ValueCallback is what gets called every time the animation is rendered. The There are also some helper `ValueCallback` subclasses such as `LottieStaticValueCallback` that takes a single value of the correct type in its constructor and will always return that. Think of it as a fire and forget value. There is also a relative value callback that offsets the real animation value by a specified amount. -#### ValueCallback classes +##### ValueCallback classes * LottieValueCallback: Either set a static value in the contructor or override getValue() to set the value on every frame. * LottieRelativeTYPEValueCallback: Either set a static value in the constructor or override getOffset() to set a value taht will be applied as an offset to the actual animation value on each frame. TYPE is the same type as the LottieProperty parameter. * LottieInterpolatedTYPEValue: Supply a start value, end value, and optional interpolator to have the value automatically interpolate across the entire animation. TYPE is the same type as the LottieProperty parameter. -## Usage -```java - animationView.addValueCallback( - new KeyPath("Shape Layer", "Rectangle", "Fill"), - LottieProperty.COLOR, - new LottieStaticValueCallback<>(Color.RED)); -``` - -```java +### Usage +```kotlin animationView.addValueCallback( - new KeyPath("Shape Layer", "Rectangle", "Fill"), - LottieProperty.COLOR, - (frameInfo) -> { - return overallProgress < 0.5 ? Color.GREEN : Color.RED; - } -); + KeyPath("Shape Layer", "Rectangle", "Fill"), + LottieProperty.COLOR, + { Color.RED } +) ``` -or Kotlin -```kotlin - animationView.addValueCallback( - KeyPath("Shape Layer", "Rectangle", "Fill"), - LottieProperty.COLOR_FILTER) { Color.RED }; -``` ```kotlin animationView.addValueCallback( KeyPath("Shape Layer", "Rectangle", "Fill"), - LottieProperty.COLOR_FILTER) { frameInfo -> frameInfo.overallProgress < 0.5 ? Color.GREEN : Color.RED } -); + LottieProperty.COLOR, + { if (it.overallProgress < 0.5) Color.GREEN else Color.RED } +) ``` -## Animatable Properties +### Animatable Properties The following value can be modified: -### Transform: - * `TRANSFORM_ANCHOR_POINT` - * `TRANSFORM_POSITION` - * `TRANSFORM_OPACITY` - * `TRANSFORM_SCALE` - * `TRANSFORM_ROTATION` - -### Fill: - * `COLOR` (non-gradient) - * `OPACITY` - * `COLOR_FILTER` - -### Stroke: - * `COLOR (non-gradient)` - * `STROKE_WIDTH` - * `OPACITY` - * `COLOR_FILTER` - -### Ellipse: - * `POSITION` - * `ELLIPSE_SIZE` - -### Polystar: - * `POLYSTAR_POINTS` - * `POLYSTAR_ROTATION` - * `POSITION` - * `POLYSTAR_OUTER_RADIUS` - * `POLYSTAR_OUTER_ROUNDEDNESS` - * `POLYSTAR_INNER_RADIUS` (star) - * `POLYSTAR_INNER_ROUNDEDNESS` (star) - -### Repeater: - * All transform properties - * `REPEATER_COPIES` - * `REPEATER_OFFSET` - * `TRANSFORM_ROTATION` - * `TRANSFORM_START_OPACITY` - * `TRANSFORM_END_OPACITY` - -### Layers: - * All transform properties - * `TIME_REMAP` (composition layers only) - -## Notable Properties - -### Time Remapping -Compositions and precomps (composition layers) have an a time remap proprty. If you set a value callback for time remapping, you control the progress of a specific layer. To do so, return the desired time value in seconds from your value callback. -### Color Filters -The only animatable property that doesn't map 1:1 to an After Effects property is the color filter property you can set on fill content. This can be used to set blend modes on layers. It will only apply to the color of that fill, not any overlapping content. +| Transform | Layer | Fill | Stroke | Ellipse | Polystar | Repeater | Image | Text | +|------------------------|---------------------------|--------------|--------------|--------------|----------------------------|-------------------------|--------------|---------------| +| TRANSFORM_ANCHOR_POINT | TRANSFORM_ANCHOR_POINT | COLOR | STROKE_COLOR | ELLIPSE_SIZE | POLYSTAR_POINTS | REPEATER_COPIES | IMAGE | COLOR | +| TRANSFORM_POSITION | TRANSFORM_POSITION | OPACITY | STROKE_WIDTH | POSITION | POLYSTAR_ROTATION | REPEATER_OFFSET | COLOR_FILTER | STROKE_COLOR | +| TRANSFORM_OPACITY | TRANSFORM_OPACITY | COLOR_FILTER | COLOR_FILTER | | POSITION | TRANSFORM_ROTATION | | STROKE_WIDTH | +| TRANSFORM_SCALE | TRANSFORM_SCALE | | OPACITY | | POLYSTAR_OUTER_RADIUS | TRANSFORM_START_OPACITY | | TEXT_TRACKING | +| TRANSFORM_ROTATION | TRANSFORM_ROTATION | | | | POLYSTAR_OUTER_ROUNDEDNESS | TRANSFORM_END_OPACITY | | TEXT_SIZE | +| | TIME_REMAP (composition) | | | | POLYSTAR_INNER_RADIUS | | | TYPEFACE | +| | | | | | | | | TEXT | -## Migrating from the old `addColorFilter` API -If you were using the old API to dynamically change a color, you will need to migrate to the new one. To do so upgrade your code as follows: -```java -animationView.addColorFilter(colorFilter); -``` -becomes -```java -animationView.addValueCallback(new KeyPath("**"), LottieProperty.COLOR_FILTER, new LottieValueCallback(colorFilter)); -``` ------- -```java -animationView.addColorFilterToLayer("hello_layer", colorFilter); -``` -becomes -```java -animationView.addValueCallback(new KeyPath("hello_layer", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback(colorFilter)); -``` ------- -```java -animationView.addColorFilterToContent("hello_layer", "hello", colorFilter); -``` -becomes -```java +### Notable Properties -animationView.addValueCallback(new KeyPath("hello_layer", "**", "hello"), LottieProperty.COLOR_FILTER, new LottieValueCallback(colorFilter)); -``` ------- -```java -animationView.clearColorFilters(); -``` -becomes -```java -animationView.addValueCallback(new KeyPath("**"), LottieProperty.COLOR_FILTER, null); -``` +#### Time Remapping +Compositions and precomps (composition layers) have an a time remap proprty. If you set a value callback for time remapping, you control the progress of a specific layer. To do so, return the desired time value in seconds from your value callback. + +#### Color Filters +The only animatable property that doesn't map 1:1 to an After Effects property is the color filter property you can set on fill content. This can be used to set blend modes on layers. It will only apply to the color of that fill, not any overlapping content. +--- # Images Lottie is designed to work with vector shapes. Although Lottie supports rendering images, there are disadvantages to using them: @@ -336,41 +243,32 @@ Lottie is designed to work with vector shapes. Although Lottie supports renderin * They get pixelated when scaled. * They add complexity to the animation. Instead of one file, you have the json file plus all of the images. -A common cause of images in Lottie files is that bodymovin exports Illustrator layers from After Effects as images. If you think this might be the case, follow the instructions [here](/after-effects/artwork-to-lottie-walkthrough.md). +A common cause of images in Lottie files is that bodymovin exports Illustrator layers from After Effects as images. If you think this might be the case, follow the instructions [here](/after-effects.md). -## Setting your images +### Setting your images You can set Lottie images in three ways: -### src/assets -If you do need to use images, put the images in a folder inside of `src/assets` and don't change the filenames of the images. You then need to direct Lottie to the assets folder where the images are stored by calling `setImageAssetsFolder` on `LottieAnimationView` or -`LottieDrawable` with the relative folder inside of assets. Again,make sure that the images that -bodymovin export are in that folder with their names unchanged (should be img_#). -If you use `LottieDrawable` directly. -You should call `recycleBitmaps` when you are done animating. -### Zip file +#### src/assets +Put the images in a folder inside of `src/assets` and don't change the filenames of the images. + + +Then, tell Lottie to the assets folder where the images are stored by calling `setImageAssetsFolder` on `LottieAnimationView` or +`LottieDrawable` with the relative folder inside of assets or with the `app:lottie_imageAssetsFolder` attribute on your LottieAnimationView. + +Again,make sure that the images that bodymovin exports are in that folder with their names unchanged (should be img_#). + +#### Zip file Alternatively, you can create a zip file with your json and images together. Lottie can unzip and read the contents. This can be done for local files or from a url. -### Providing your own images -Sometimes, you don't have the images bundled with the device. You may do this to save space in your apk or if you downloaded the animation from the network. To handle this case, you can set an `ImageAssetDelegate` on your `LottieAnimationView` or `LottieDrawable`. The delgate will be called every time Lottie tries to render an image. It will pass the image name and ask you to return the bitmap. If you don't have it yet (if it's still downloading, for example) then just return null and Lottie will continue to ask on every frame until you return a non-null value. - - ```java -animationView.setImageAssetDelegate(new ImageAssetDelegate() { - @Override public Bitmap fetchBitmap(LottieImageAsset asset) { - if (downloadedBitmap == null) { - // We don't have it yet. Lottie will keep - // asking until we return a non-null bitmap. - return null; - } - return downloadedBitmap; - } -}); -``` +#### Providing your own images +Sometimes, you don't have the images bundled with the device. You may do this to save space in your apk or if you downloaded the animation from the network. To handle this case, you can use dynamic properties with `LottieProperty.IMAGE` +--- # What is the impact of Lottie on APK size? Very small: -* ~800 methods. -* 111kb uncompressed. -* 45kb gzipped when downloaded through the Play Store. +* ~1600 methods. +* 287kb uncompressed. +--- # Lottie vs Android Vector Drawable (AVD) There are two ways to render After Effects animations: @@ -378,7 +276,7 @@ There are two ways to render After Effects animations: 2. Export AndroidVectorDrawable xml with Bodymovin and play it using the Android SDK. ## Pros of Lottie -* Supports a much larger set of After Effects features. See [supported features](/after-effects/supported-features.md) for a full list. +* Supports a much larger set of After Effects features. See [supported features](/supported-features.md) for a full list. * Manually set progress to hook up an animation to a gesture, event, etc. * Download animations from the network. * Dynamic playback speed. @@ -388,18 +286,13 @@ There are two ways to render After Effects animations: ## Pros of AnimatedVectorDrawable * Faster peformance due to the animation running on the [RenderThread](https://medium.com/@workingkills/understanding-the-renderthread-4dc17bcaf979) vs the main thread. - -## Bodymovin AVD exporter -Bodymovin can export some animations directly as AVDs if they suit your needs better. -To do so, just check the AVD checkbox in the bodymovin settings: -![AVD](/images/BodymovinAvd.png) -This support is very experimental and only supports a subset of the functionality of lottie and avd. - +--- # Performance ## Masks and Mattes Masks and mattes on android have the larges performance hit. Their performance hit is also proportional to the intersection bounds of the masked/matted layer and the mask/matte so the smaller the mask/matte, the less of a performance hit there will be. On Android, if you are using masks or mattes, there will be a several X performance improvement when using hardware acceleration. +For debugging purposes, Lottie can outline all masks and mattes in your animation. To do that, just call `setOutlineMasksAndMattes(true)` on your `LottieAnimationView` or `LottieDrawable`. # Hardware Acceleration @@ -437,7 +330,7 @@ The Lottie for Android will automatically detect and report some errors. It does Check the [supported features page](/supported-features.md) on this site to see if you are using anything that isn't supported. ## Debug -Try rendering individual parts of the animation to see which feature isn't rendering correctly. See if you can narrow it down to a specific combination of shapes and effects or anything more specific than "it doesn't look right". If the issue should be supported and isn't, file an issue on the appropriate lottie github page with a description and a zip of the aep file. +Try rendering individual parts of the animation to see which feature isn't rendering correctly. See if you can narrow it down to a specific combination of shapes and effects or anything more specific than "it doesn't look right". If the issue should be supported and isn't, file an issue on the appropriate lottie GitHub page with a description and a zip of the aep file. ## Missing merge paths Merge paths are only available on KitKat and above so you must manually enable them using `enableMergePathsForKitKatAndAbove()` @@ -449,4 +342,4 @@ Make sure you are using the latest version of Lottie. ![YourKit](https://www.yourkit.com/images/yklogo.png) -Performance and memory testing was aided by [YourKit](https://www.yourkit.com/java/profiler/) which provides powerful performance and memory profiling tools for Java. \ No newline at end of file +Performance and memory testing was aided by [YourKit](https://www.yourkit.com/java/profiler/) which provides powerful performance and memory profiling tools for Java. diff --git a/community-showcase.md b/community-showcase.md index c5350ec..d97276b 100644 --- a/community-showcase.md +++ b/community-showcase.md @@ -74,6 +74,18 @@ A Bitcoin/Blockchain startup based in Milan uses Lottie to better explain some ![Conio](/images/ShowcaseConio.gif) ## Galaxy Watch -Galaxy watch (Tizen OS) uses lottie for watchface and workout application. +Galaxy watch (Tizen OS) uses lottie for watchface and workout application. ![Galaxy Watch](/images/ShowcaseGalaxyWatch.gif) + +## Others +![Example1](images/Introduction_01_sm.gif) + + +![Example2](images/Introduction_02_sm.gif) + + +![Example3](images/Introduction_03_sm.gif) + + +![Example4](images/Introduction_04_sm.gif) diff --git a/docs.md b/docs.md index 84e8978..e848c15 100644 --- a/docs.md +++ b/docs.md @@ -1,8 +1,13 @@ -# Contributing to docs +## Contributing to the docs directly on GitHub (easy) +Because the Lottie docs are created directly from the markdown in this repo, you can use the GitHub web editor to edit and propose changes to the docs directly from your browser without any knowledge of git. +To do that, find the markdown file with the docs you want to edit and follow [GitHub's instructions](https://docs.github.com/en/free-pro-team@latest/github/managing-files-in-a-repository/editing-files-in-another-users-repository) to edit and propose changes to a markdown file. Once approved, the docs will be updated immediately. -1. Fork [airbnb/lottie](https://github.com/airbnb/lottie) -1. Make desired changes to markdown docs. Each platform is in one markdown file. - * The sidebar will automatically be populated by the H1 titles. -1. Install the docsify cli with `npm i docsify-cli -g` -1. Run `docsify serve docs` to run a local webserver to test your docs. Modify docs as needed. -1. Put up a pull request on [airbnb/lottie](https://github.com/airbnb/lottie). +## Contributing to the docs by forking this repo (still pretty easy) +[http://airbnb.io/lottie](http://airbnb.io/lottie) runs on [docsify](https://docsify.js.org/#/?id=docsify). Docsify was chosen because it takes hosted markdown and generates the page dynamically. That means that simply updating the markdown files here is all that is needed to update [http://airbnb.io/lottie](http://airbnb.io/lottie). + +1. Fork and clone this repo. +1. Install docsify: `sudo npm install -g docsify-cli`. +1. Startup the local docsify server with `docsify serve .` from the root of this repo. +1. Edit the markdown and verify your changes on the localhost url outputted from the `docsify serve` command. +1. Put up a pull request to this repo and tag `@gpeal` +1. Enjoy the updated docs! diff --git a/home.md b/home.md new file mode 100644 index 0000000..54964fa --- /dev/null +++ b/home.md @@ -0,0 +1,118 @@ +# Lottie for [Android](https://github.com/airbnb/lottie-android), [iOS](https://github.com/airbnb/lottie-ios), [Web](https://github.com/airbnb/lottie-web), [React Native](https://github.com/airbnb/lottie-react-native), and [Windows](https://aka.ms/lottie) + +Lottie is a library for Android, iOS, Web, and Windows that parses [Adobe After Effects](http://www.adobe.com/products/aftereffects.html) animations exported as JSON with [Bodymovin](https://github.com/airbnb/lottie-web) and renders them natively on mobile and on the web! + +For the first time, designers can create **and ship** beautiful animations without an engineer painstakingly recreating them by hand. They say a picture is worth 1,000 words, so here you go: + +![Lottie Logo animation](images/Introduction_00_sm.gif ":size=500") + +The above animation was created in After Effects and can be rendered natively across all platforms with a simple JSON file. + +## Sponsors + +Lottie is made possible because of our supporters on GitHub Sponsors and Open Collective. To learn more, please check out our [sponsorship page](/sponsorship.md). + +We would especially like to thank our sponsorships from + +[![Lottiefiles](images/lottiefiles.svg ":size=300")](https://www.lottiefiles.com/) + +[![Lottie Lab](images/lottielab.png ":size=300")](https://lottielab.io/) + +[![Airbnb](images/airbnb.svg ":size=300")](https://www.airbnb.com/) + +[![Emerge Tools](images/emerge.png ":size=300")](https://www.emergetools.com/) + +[![Stream](images/stream.png ":size=300")](https://getstream.io/chat/?utm_source=OpenCollective_Lottie&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=Lottie_July2022_Chat_klmh22) + +[![Coinbase](images/coinbase.svg ":size=300")](https://www.coinbase.com/) + +Read more about it on our [blog post](http://airbnb.design/introducing-lottie/) +Or get in touch on GitHub or via lottie@airbnb.com + +## Sample App + + + + + + +
+ Get it on Google Play + + English badge +
+ +You can build the sample app for Android yourself or download it from the [Play Store](https://play.google.com/store/apps/details?id=com.airbnb.lottie). The sample app includes some built in animations but also allows you to load an animation from internal storage or from a url. + +For Windows, you can get the [Lottie Viewer app](https://aka.ms/lottieviewer) to preview Lottie animation and codegen classes and the [Lottie Samples app](https://aka.ms/lottiesamples) to get started with code samples and simple tutorials. + +## Shipping something with Lottie? + +We would love to feature your work in our [community showcase](/community-showcase.md)! To do so, Put up a PR on [github.com/lottie](https://github.com/airbnb/lottie) with a change to [community-showcase.md](https://github.com/airbnb/lottie/blob/master/community-showcase.md) with a description and gif of your animation. +We also have an internal regression testing repo that we can use to prevent causing regressions with your animations. + +## Alternatives + +1. Build animations by hand. Building animations by hand is a huge time commitment for design and engineering across Android and iOS. It's often hard or even impossible to justify spending so much time to get an animation right. +1. Gifs. Gifs are more than double the size of a bodymovin JSON and are rendered at a fixed size that can't be scaled up to match large and high density screens. +1. Png sequences. Png sequences are even worse than gifs in that their file sizes are often 30-50x the size of the bodymovin JSON and also can't be scaled up. +1. Animated Vector Drawable (Android only). More performant because it runs on the RenderThread instead of the main thread. Supports only a subset of Lottie features. Progress can't be manually set. Doesn't support text or dynamic colors. Can't be loaded programmatically or over the internet. + +## Why is it called Lottie? + +Lottie is named after a German film director and the foremost pioneer of silhouette animation. Her best known films are The Adventures of Prince Achmed (1926) โ€“ the oldest surviving feature-length animated film, preceding Walt Disney's feature-length Snow White and the Seven Dwarfs (1937) by over ten years +[The art of Lotte Reineger](https://www.youtube.com/watch?v=LvU55CUw5Ck&feature=youtu.be) + +## Contributing to Documentation + +Contributors are more than welcome. Just put up a PR to [github.com/airbnb/lottie](https://github.com/airbnb/lottie). + +## Issues or feature requests? + +File GitHub issues for anything that is unexpectedly broken. If an After Effects file is not working, please attach it to your issue. Debugging without the original file is much more difficult. + +## Articles, Interviews & Podcasts + +Here are some articles and podcasts from the Lottie team @ Airbnb + +[Behind the scenes: Why we built Lottie, our new open-source animation tool here.](https://airbnb.design/introducing-lottie/) + +[Dig into the details and back story with Brandon Withrow and Salih Abdul-Karim on the School of motion podcast](https://www.schoolofmotion.com/blog/after-effects-to-code-lottie-from-airbnb) + +[Learn more about Lottie from Gabriel Peal on the Fragmented Podcast](http://fragmentedpodcast.com/episodes/82/) + +[Lottie Animation with Brandon Withrow and Gabriel Peal on Software engineering daily podcast](https://softwareengineeringdaily.com/2017/08/10/lottie-animation-with-brandon-withrow-and-gabriel-peal/) + +[Announcing Lottie 4.0 for iOS](https://medium.com/airbnb-engineering/announcing-lottie-4-0-for-ios-d4d226862a54): A new rendering engine with significant performance improvements powered by Core Animation + +[Moving Lottie Swiftly into the Future](https://medium.com/airbnb-engineering/lottie-and-swift-at-airbnb-e0c85dc365e7): A personal story on how Airbnb rewrote the popular open source library Lottie in a new language + +## Community articles and videos + +Here are some links from around the community + +[A Lottie to Like](https://t.co/dadjvgv9vk) by Nick Butcher + +[Creating better user experiences with animations and Lottie](https://pspdfkit.com/blog/2017/creating-better-user-experiences-with-animations-and-lottie/) by Samo Korosec and Stefan Keileithner + +[10 amazing web animations with Lottie \(In Spanish\)](https://www.youtube.com/watch?v=IFp3tyy3cRA) by AnimatiCSS + +[How to use Lottie \(In Spanish\)](https://www.youtube.com/watch?v=hLUBXENQSOc) by AnimatiCSS + +[How to use Lottie \(In Chinese\)](https://medium.com/as-a-product-designer/ๅฟƒๅพ—ๅˆ†ไบซ-ๅฆ‚ไฝ•ไฝฟ็”จlottie-ๅฐ‡ๅฎŒ็พŽๅ‹•็•ซ100-ๅ‘ˆ็พๅœจ็”ขๅ“ไธŠ-7ac7107abfa5) by Patty Wu + +[A Beginningโ€™s Guide to Lottie: Creating Amazing Animations in iOS Apps](https://www.appcoda.com/lottie-beginner-guide/#) by Simon NG + +[Take your animations to the next level with Airbnb framework, Lottie](https://medium.com/@jamesrochabrun/take-your-animations-to-the-next-level-with-airbnb-framework-lottie-ab6c6152acba) by James Rochabrun + +[iOS Swift Tutorial: Animations with After Effects and Lottie](https://www.youtube.com/watch?v=ESjFEaZx7UI) by Brian Advent + +[iOS Swift Tutorial: Interactive Animations with After Effects and Lottie](https://www.youtube.com/watch?v=QyL-jp9bFdM) by Brian Advent + +[After Effects for wiOS Developers: Dynamic Content in Animations](https://youtu.be/2HhgLir6Jz0?list=PLUDTy1CWIw-qu2EuzNVFQawyW5jmC5W7G) by Brian Advent + +[Creating cool animations in android using Lottie](https://www.youtube.com/watch?v=T4v72xJqNpQ)[Chetan Sachdeva](https://www.youtube.com/channel/UC_4TBWZcI-tdZ02wESTRVNw) by Chetan Sachdeva + +[Boost Your User Experience with Lottie for React Native](https://blog.reactnativecoach.com/boost-your-user-experience-with-lottie-for-react-native-5da1ac589982) by Samuli Hakoniemi + +[How to use 'Lottie' in Framer X](https://www.youtube.com/watch?v=GflnbO5RMZI) by ruucm diff --git a/images/Web-StrokeCutoffMaskingDemo.png b/images/Web-StrokeCutoffMaskingDemo.png new file mode 100644 index 0000000..e4c7d9a Binary files /dev/null and b/images/Web-StrokeCutoffMaskingDemo.png differ diff --git a/images/airbnb.svg b/images/airbnb.svg new file mode 100644 index 0000000..cfa67db --- /dev/null +++ b/images/airbnb.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/images/coinbase.svg b/images/coinbase.svg new file mode 100644 index 0000000..8970548 --- /dev/null +++ b/images/coinbase.svg @@ -0,0 +1,31 @@ + + + + + + diff --git a/images/emerge.png b/images/emerge.png new file mode 100644 index 0000000..76f7727 Binary files /dev/null and b/images/emerge.png differ diff --git a/images/lottiefiles.svg b/images/lottiefiles.svg new file mode 100644 index 0000000..03b2bad --- /dev/null +++ b/images/lottiefiles.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/images/lottielab.png b/images/lottielab.png new file mode 100644 index 0000000..72ac42c Binary files /dev/null and b/images/lottielab.png differ diff --git a/images/stream.png b/images/stream.png new file mode 100644 index 0000000..c4837b0 Binary files /dev/null and b/images/stream.png differ diff --git a/images/tonal.svg b/images/tonal.svg new file mode 100644 index 0000000..71b3515 --- /dev/null +++ b/images/tonal.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/index.html b/index.html index 6010a3c..288f1e6 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ Lottie Docs - + @@ -23,6 +23,7 @@ name: 'Lottie', repo: 'https://github.com/airbnb/lottie', loadSidebar: true, + homepage: 'home.md', subMaxLevel: 1, alias: { '/.*/_sidebar.md': '/_sidebar.md' diff --git a/ios-contributor.md b/ios-contributor.md index eeeea1a..019550e 100644 --- a/ios-contributor.md +++ b/ios-contributor.md @@ -1,9 +1,9 @@ +> The doc was last updated in 2019 and is no longer up to date. It no longer reflects the current project structure, and doesn't include any content about the Core Animation rendering engine. This doc is left available as documentation of the Main Thread rendering engine, which hasn't changed significantly since this documentation was written. + # Lottie-iOS Render System Documentation The purpose of this document is to explain how Lottie's render system works. -For questions reach out to the author: [Brandon Withrow](https://twitter.com/theWithra) - ## Check Before Submitting Before submitting a PR to Lottie please run through the following checklist. diff --git a/ios-migration.md b/ios-migration.md deleted file mode 100644 index 1f16d23..0000000 --- a/ios-migration.md +++ /dev/null @@ -1,40 +0,0 @@ -# Migrating from Lottie 2.5.3(OBJC) -> 3.0 (SWIFT) - -Lottie 3.0 is a complete rewrite of Lottie in Swift. Because of this there are some minor API changes. This guide should help you through migrating code from Lottie 2.5.2 to 3.0 - -For continued support and contribution to Objective-C please point to the official Lottie Objective-C Branch [Here](https://github.com/airbnb/lottie-ios/tree/lottie/objectiveC) - -Swift discourages the use of Prefix for names. A lot of the api changes are just the removal of `LOT` from the class name. Below is a complete list of API changes. - -To use Lottie Swift in an Objective-C project read Apple's official documentation [here](https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/importing_swift_into_objective-c) - -## Class Changes -| Lottie 2.5.2 | Lottie 3.0+ | -| --:| --:| -|`LOTAnimationView`|`AnimationView`| -|`LOTComposition`|`Animation`| -|`LOTKeypath`|`AnimationKeypath`| -|`LOTAnimationCache`|`AnimationCacheProvider`| -|`LOTCacheProvider`|`AnimationImageProvider`| -|`LOTValueDelegate`|`AnyValueProvider`| -|`LOTAnimatedControl`|`AnimatedControl`| -|โ›”๏ธ|`AnimatedButton`| -|`LOTAnimatedSwitch`|`AnimatedSwitch`| - -## Method Changes - -| Lottie 2.5.2 | Lottie 3.0+ | -| --:| --:| -|`LOTAnimationView.sceneModel`|`AnimationView.animation`| -|`LOTAnimationView.loopAnimation`|`AnimationView.loopMode`| -|`LOTAnimationView.autoReverseAnimation`|`AnimationView.loopMode`| -|`LOTAnimationView.animationProgress`|`AnimationView.currentProgress`| -|`LOTAnimationView.cacheEnable`|โ›”๏ธ(Cache is passed in on init)| -|`LOTAnimationView.setValueDelegate:forKeypath:`|`AnimationView.setValueProvider:keypath:`| -|`LOTComposition.animationNamed:`|`Animation.named:`| -|`LOTComposition.animationWithFilePath:`|`Animation.filepath:`| -|`LOTComposition.animationNamed:inBundle:`|`Animation.named:bundle:`| -|`LOTComposition.animationFromJSON:`|โ›”๏ธ(`Animation` is Encodable/Decodable from data on it's own.)| - diff --git a/ios.md b/ios.md index cadc19c..4f5aef9 100644 --- a/ios.md +++ b/ios.md @@ -1,45 +1,33 @@ +# Supported Platforms -> ==**Announcement**==: As of 3.0 Lottie has been completely rewritten in Swift 4.2! For Objective-C support please use Lottie 2.5.3. Read Migration doc [Here](/ios-migration.md). - -## Contents - -- [Installing Lottie](#installing-lottie) -- [Quick Start](#quick-start) -- [Animation Model](#animation-model) - - [Loading Animation](#loading-animation) -- [Animation View](#animation-view) - - [Supplying Images](#supplying-images) - - [Playing Animations](#playing-animations) - - [Animation Settings](#animation-settings) - - [Using Markers](#using-markers) - - [Dynamic Animation Properties](#dynamic-animation-properties) - - [Adding Views to Animations](#adding-views-to-animations) - - [Enabling and Disabling Animation Nodes](#enabling-and-disabling-animation-nodes) -- [Image Provider](#image-provider) - - [BundleImageProvider](#bundleimageprovider) - - [FilepathImageProvider](#filepathimageprovider) -- [Animation Cache](#animation-cache) - - [LRUAnimationCache](#lruanimationcache) -- [Value Providers](#value-providers) - - [Primitives](#primitives) - - [Prebuilt Providers](#prebuilt-providers) -- [Animated Control](#animated-control) -- [Animated Switch](#animated-switch) -- [Animated Button](#animated-button) -- [Examples](#examples) - - [Changing Animations at Runtime](#changing-animations-at-runtime) -- [Supported After Effects Features](#supported-after-effects-features) -- [Alternatives](#alternatives) -- [Why is it Called Lottie?](#why-is-it-called-lottie) -- [Contributing](#contributing) -- [Issues or Feature Requests?](#issues-or-feature-requests) -## Installing Lottie -Lottie supports [CocoaPods](https://cocoapods.org/) and [Carthage](https://github.com/Carthage/Carthage) (Both dynamic and static). Lottie is written in ***Swift 4.2***. -### Github Repo - -You can pull the [Lottie Github Repo](https://github.com/airbnb/lottie-ios/) and include the Lottie.xcodeproj to build a dynamic or static library. - -### CocoaPods +The [lottie-ios](https://github.com/airbnb/lottie-ios) package supports iOS, macOS, tvOS, and visionOS. + +# Installing Lottie + +Lottie supports [Swift Package Manager](https://www.swift.org/package-manager/), [CocoaPods](https://cocoapods.org/), and [Carthage](https://github.com/Carthage/Carthage) (Both dynamic and static). + +## Github Repo + +You can pull the [Lottie Github Repo](https://github.com/airbnb/lottie-ios/) and include the `Lottie.xcodeproj` to build a dynamic or static library. + +## Swift Package Manager + +To install Lottie using [Swift Package Manager](https://github.com/apple/swift-package-manager) you can follow the [tutorial published by Apple](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app) using the URL for the Lottie repo with the current version: + +1. In Xcode, select โ€œFileโ€ โ†’ โ€œAdd Packages...โ€ +1. Enter https://github.com/airbnb/lottie-spm.git + +or you can add the following dependency to your `Package.swift`: + +```swift +.package(url: "https://github.com/airbnb/lottie-spm.git", from: "4.5.0") +``` + +When using Swift Package Manager we recommend using the [lottie-spm](https://github.com/airbnb/lottie-spm) repo instead of the main lottie-ios repo. The main git repository for [lottie-ios](https://github.com/airbnb/lottie-ios) is somewhat large (300+ MB), and Swift Package Manager always downloads the full repository with all git history. The [lottie-spm](https://github.com/airbnb/lottie-spm) repo is much smaller (less than 500kb), so can be downloaded much more quickly. + +Instead of downloading the full git history of Lottie and building it from source, the lottie-spm repo just contains a pointer to the precompiled XCFramework included in the [latest lottie-ios release](https://github.com/airbnb/lottie-ios/releases/latest) (typically ~8MB). If you prefer to include Lottie source directly your project, you can directly depend on the main lottie-ios repo by referencing `https://github.com/airbnb/lottie-ios.git` instead. + +## CocoaPods Add the pod to your Podfile: ```ruby pod 'lottie-ios' @@ -49,11 +37,12 @@ And then run: ```ruby pod install ``` -After installing the cocoapod into your project import Lottie with +After installing the cocoapod into your project import Lottie with ```swift import Lottie ``` -### Carthage + +## Carthage Add Lottie to your Cartfile: ``` github "airbnb/lottie-ios" "master" @@ -65,25 +54,28 @@ carthage update ``` In your application targets โ€œGeneralโ€ tab under the โ€œLinked Frameworks and Librariesโ€ section, drag and drop lottie-ios.framework from the Carthage/Build/iOS directory that `carthage update` produced. -[Back to contents](#contents) - -## Quick Start +# Quick Start Lottie loads and renders animations and vectors exported in the bodymovin JSON format. Bodymovin JSON can be created and exported from After Effects with [bodymovin](https://github.com/bodymovin/bodymovin), Sketch with [Lottie Sketch Export](https://github.com/buba447/Lottie-Sketch-Export), and from [Haiku](https://www.haiku.ai). - - Lottie-iOS looks to `UIImageView` for its API. The basic API is broken into two parts: - - `Animation` - The backing model for an animation that is deserialized from a json file. - - `AnimationView` - A `UIView` subclass responsible for loading and rendering the `Animation` + +Lottie provides components for displaying and rendering Lottie animations, which are compatible with SwiftUI, UIKit, and Core Animation: + - `LottieAnimationLayer`: a Core Animation `CALayer` subclass that renders Lottie animations + - `LottieAnimationView`: a UIKit `UIView` subclass that wraps `LottieAnimationLayer` and provides the same set of APIs. + - `LottieView`: a SwiftUI `View` that wraps the UIKit `LottieAnimationView` and provides a SwiftUI-style declarative API. + +`LottieAnimation` is the main type for representing a Lottie animation. It supplies many static helper methods for loading `LottieAnimation`s, including asynchronously from URLs. Lottie also supports the [dotLottie](https://dotlottie.io/) format, available as the `DotLottieFile` type. + +## UIKit You can quickly load a Lottie animation with: ```swift -let starAnimationView = AnimationView(name: "StarAnimation") +let starAnimationView = LottieAnimationView(name: "StarAnimation") ``` -Additionally you can choose to load an `AnimationView` without any animation, and set the animation later: +Additionally you can choose to load an `LottieAnimationView` without any animation, and set the animation later: ```swift -let starAnimationView = AnimationView() +let starAnimationView = LottieAnimationView() /// Some time later -let starAnimation = Animation.named("StarAnimation") +let starAnimation = LottieAnimation.named("StarAnimation") starAnimationView.animation = starAnimation ``` You can load animations from a specific bundle, a filepath, or even asynchronously from a URL. Read more about loading animations [Here](#loading-animation) @@ -91,26 +83,62 @@ You can load animations from a specific bundle, a filepath, or even asynchronous After loading an animation it can be played with: ```swift starAnimationView.play { (finished) in - /// Animation finished + /// LottieAnimation finished } ``` Read more about playing animations [Here](#playing-animations) -[Back to contents](#contents) -## Animation Model -The `Animation` model is the top level model object in Lottie. An `Animation` holds all of the animation data backing a Lottie Animation. `Animations` are deserialized from JSON. -Codable; see JSON schema [here](https://github.com/airbnb/lottie-web/tree/master/docs/json). +## SwiftUI + +The `LottieView` SwiftUI view provides many of the same APIs as the UIKit `LottieAnimationView`. + +For example, here's how you load and play a simple local animation: + +```swift +LottieView(animation: .named("StarAnimation")) + .playing() +``` + +`LottieView` also provides a convenient API for loading animations asynchronously, e.g. by downloading them from a URL: + +```swift +LottieView { + try await LottieAnimation.loadedFrom(url: myAnimationDownloadURL) +} +.playing() +``` + +You can use an `@State` property with a `LottiePlaybackMode` to control animation playback. For example, here's how you can trigger an animation to be played in response to a button being pressed: + +```swift +@State var playbackMode = LottiePlaybackMode.paused + +var body: some View { + LottieView(animation: .named("StarAnimation")) + .playbackMode(playbackMode) + .animationDidFinish { _ in + playbackMode = .paused + } + + Button { + playbackMode = .playing(.fromProgress(0, toProgress: 1, loopMode: .playOnce)) + } label: { + Image(systemName: "play.fill") + } +} +``` - `Animation` is also fully `codable`. ==Animations can be decoded, and encoded to JSON!== +# LottieAnimation Model +The `LottieAnimation` model is the top level model object in Lottie. An `LottieAnimation` holds all of the animation data backing a Lottie LottieAnimation. `LottieAnimation`s are deserialized from JSON using the schema defined [here](https://github.com/airbnb/lottie-web/tree/master/docs/json). -### Loading Animation -There are a variety of ways to load an `Animation` on its own. Additionally you can load an animation while allocating an `AnimationView` through one of the convenience initializers on `AnimationView`. +## Loading LottieAnimation +There are a variety of ways to load an `LottieAnimation` on its own. Additionally you can load an animation while initializing an `LottieAnimationView` through one of the convenience initializers on `LottieAnimationView`. -Animations can be stored in an `AnimationCacheProvider` to reduce the overhead of deserializing the same animations over and over. Read more [here](#animation-cache). +Animations can be stored in an `AnimationCacheProvider` to reduce the overhead of deserializing the same animations over and over. Read more [here](#animation-cache). # -#### Loading from a Bundle +### Loading from a Bundle ```swift -Animation.named(_ name: String, bundle: Bundle, subdirectory: String?, animationCache: AnimationCacheProvider?) -> Animation? +LottieAnimation.named(_ name: String, bundle: Bundle, subdirectory: String?, animationCache: AnimationCacheProvider?) -> LottieAnimation? ``` Loads an animation model from a bundle by its name. Returns `nil` if an animation is not found. @@ -123,18 +151,18 @@ Parameters: Example: ```swift /// Load from the main bundle. -let animation = Animation.named("StarAnimation") +let animation = LottieAnimation.named("StarAnimation") /// Load from a specific bundle/ -let animation = Animation.named("StarAnimation", bundle: myBundle) +let animation = LottieAnimation.named("StarAnimation", bundle: myBundle) /// Load from a subdirectory in a bundle. -let animation = Animation.named("StarAnimation", subdirectory: "Animations") +let animation = LottieAnimation.named("StarAnimation", subdirectory: "Animations") /// Load with an animation cache. -let animation = Animation.named("StarAnimation", animationCache: LRUAnimationCache.sharedCache) +let animation = LottieAnimation.named("StarAnimation", animationCache: LRUAnimationCache.sharedCache) ``` -# -#### Loading from a Filepath + +### Loading from a Filepath ```swift -Animation.filepath(_ filepath: String, animationCache: AnimationCacheProvider?) -> Animation? +LottieAnimation.filepath(_ filepath: String, animationCache: AnimationCacheProvider?) -> LottieAnimation? ``` Loads an animation model from an absolute filepath. Returns `nil` if an animation is not found. @@ -144,37 +172,34 @@ Parameters: Example: ```swift -let animation = Animation(filepathURL.path, animationCache: LRUAnimationCache.sharedCache) +let animation = LottieAnimation(filepathURL.path, animationCache: LRUAnimationCache.sharedCache) ``` -[Back to contents](#contents) -## Animation View -`AnimationView` is a UIView (NSView on macOS) subclass that displays animation content. `AnimationView` offers a number of ways to load, play, and even change animations. +# LottieAnimation View +`LottieAnimationView` is a UIView (NSView on macOS) subclass that displays animation content. `LottieAnimationView` offers a number of ways to load, play, and even change animations. Lottie is also available as a `LottieView` SwiftUI `View` and a `LottieAnimationLayer` Core Animation `CALayer`. -### Creating Animation Views -Animation views can be allocated with or without animation data. There are a handful of convenience initializers for initializing with animations. +## Creating LottieAnimation Views +LottieAnimation views can be allocated with or without animation data. There are a handful of convenience initializers for initializing with animations. -# -### Supplying Images -`AnimationView` uses `AnimationImageProvider` to retrieve the images for its animation. -An image provider can be supplied when the Animation View is initialized, or after by setting its `imageProvider` property. -To force an AnimationView to reload its images call `reloadImages()` on the AnimationView. +## Supplying Images +`LottieAnimationView` uses `AnimationImageProvider` to retrieve the images for its animation. +An image provider can be supplied when the LottieAnimation View is initialized, or after by setting its `imageProvider` property. +To force an LottieAnimationView to reload its images call `reloadImages()` on the LottieAnimationView. Read more about `AnimationImageProvider` [here](#image-provider) -# -### Playing Animations -#### Time +## Playing Animations +### Time There are several methods for playing animations, and portions of animations. Lottie describes Time in three ways: - Frame Time - Describes time in a frames per second format. `(Seconds * Framerate)` *eg: 0.5 second is FrameTime 12 when framerate is 24*. - Progress Time - Describes time in progress from 0 (the beginning of the animation timeline) to 1 (the end of the animation timeline). - Time - Describes time in seconds. -All three can be used to play and set time on an `AnimationView` -# -#### Basic Playing +All three can be used to play and set time on an `LottieAnimationView` + +### Basic Playing ```swift -AnimationView.play(completion: LottieCompletionBlock?) +LottieAnimationView.play(completion: LottieCompletionBlock?) ``` Plays the animation from its current state to the end of its timeline. Calls the completion block when the animation is stopped. @@ -183,14 +208,21 @@ Parameters: Example: ```swift -starAnimationView.play { (finished) in -/// Animation stopped +starAnimationView.play { finished in + /// LottieAnimation stopped } + +// SwiftUI LottieView API +LottieView(animation: myAnimation) + .playing() + .animationDidFinish { finished in + /// LottieAnimation did finish + } ``` -# -#### Play with Progress Time + +### Play with Progress Time ```swift -AnimationView.play(fromProgress: AnimationProgressTime?, toProgress: AnimationProgressTime, loopMode: LottieLoopMode?, completion: LottieCompletionBlock?) +LottieAnimationView.play(fromProgress: AnimationProgressTime?, toProgress: AnimationProgressTime, loopMode: LottieLoopMode?, completion: LottieCompletionBlock?) ``` Plays the animation from a `Progress Time` to a `Progress Time` with options. @@ -204,11 +236,15 @@ Example: ```swift /// Play only the last half of an animation. animationView.play(fromProgress: 0.5, toProgress: 1) + +// SwiftUI LottieView API +LottieView(animation: myAnimation) + .playing(.fromProgress(0.5, toProgress: 1, loopMode: .playOnce)) ``` -# -#### Play with Frame Time + +### Play with Frame Time ```swift -AnimationView.play(fromFrame: AnimationProgressTime?, toFrame: AnimationFrameTime, loopMode: LottieLoopMode?, completion: LottieCompletionBlock?) +LottieAnimationView.play(fromFrame: AnimationProgressTime?, toFrame: AnimationFrameTime, loopMode: LottieLoopMode?, completion: LottieCompletionBlock?) ``` Plays the animation from a `Frame Time` to a `Frame Time` with options. @@ -222,13 +258,18 @@ Example: ```swift /// Play from frame 24 to 48 of an animation. animationView.play(fromFrame: 24, toFrame: 48) + + +// SwiftUI LottieView API +LottieView(animation: myAnimation) + .playing(.fromFrame(24, toFrame: 48, loopMode: .playOnce)) ``` -# -#### Play with Marker Names + +### Play with Marker Names ```swift -AnimationView.play(fromMarker: String?, toMarker: String, loopMode: LottieLoopMode?, completion: LottieCompletionBlock?) +LottieAnimationView.play(fromMarker: String?, toMarker: String, loopMode: LottieLoopMode?, completion: LottieCompletionBlock?) ``` -Plays the animation from a named marker to another marker. Markers are point in time that are encoded into the Animation data and assigned a name. +Plays the animation from a named marker to another marker. Markers are point in time that are encoded into the LottieAnimation data and assigned a name. Read more on Markers [here](#using-markers) ==NOTE==: If markers are not found the play command will exit. @@ -240,168 +281,186 @@ Parameters: Example: ```swift -/// Play from frame 24 to 48 of an animation. +/// Play from marker "ftue1_begin" to marker "ftue1_end" of an animation. animationView.play(fromMarker: "ftue1_begin", toMarker: "ftue1_end") + + +// SwiftUI LottieView API +LottieView(animation: myAnimation) + .playing(.fromMarker("ftue1_begin", toMarker: "ftue1_end", loopMode: .playOnce)) ``` -# -#### Stop + +### Stop ```swift -AnimationView.stop() +LottieAnimationView.stop() ``` Stops the currently playing animation, if any. The animation view is reset to its start frame. The previous animation's completion block will be closed with `false` Example: ```swift animationView.stop() ``` -# -#### Pause + +### Pause ```swift -AnimationView.pause() +LottieAnimationView.pause() ``` Pauses the animation in its current state. The previous animation's completion block will be closed with `false` Example: ```swift animationView.pause() + +// SwiftUI LottieView API +LottieView(animation: myAnimation) + .playbackMode(.paused) ``` -# -### Animation Settings -`AnimationView` has a variety of settings for controlling playback, and visual state. -# -#### Content Mode + +## LottieAnimation Settings +`LottieAnimationView` has a variety of settings for controlling playback, and visual state. + +### Content Mode ```swift /// iOS -var AnimationView.contentMode: UIViewContentMode { get set } +var LottieAnimationView.contentMode: UIViewContentMode { get set } /// MacOS -var AnimationView.contentMode: LottieContentMode { get set } +var LottieAnimationView.contentMode: LottieContentMode { get set } ``` -Describes how the AnimationView should resize and scale its contents. +Describes how the LottieAnimationView should resize and scale its contents. Options: -: **scaleToFill**: Animation scaled to fill the bounds of AnimationView. The animation will be stretched if the aspect of the AnimationView is different than the Animation. -: **scaleAspectFit**: Animation will be scaled to fit the AnimationView while preserving its aspect ratio. -: **scaleAspectFill**: Animation will be scaled to fill the AnimationView while preserving its aspect ratio. -: **topLeft**: Animation will not be scaled. -# -#### Background Behavior +: **scaleToFill**: LottieAnimation scaled to fill the bounds of LottieAnimationView. The animation will be stretched if the aspect of the LottieAnimationView is different than the LottieAnimation. +: **scaleAspectFit**: LottieAnimation will be scaled to fit the LottieAnimationView while preserving its aspect ratio. +: **scaleAspectFill**: LottieAnimation will be scaled to fill the LottieAnimationView while preserving its aspect ratio. +: **topLeft**: LottieAnimation will not be scaled. + +### Background Behavior ```swift -var AnimationView.backgroundBehavior: LottieBackgroundBehavior { get set } +var LottieAnimationView.backgroundBehavior: LottieBackgroundBehavior { get set } ``` -Describes the behavior of an AnimationView when the app is moved to the background. (iOS only) +Describes the behavior of an LottieAnimationView when the app is moved to the background. (iOS only) -The default is `.pause` +The default is `.continuePlaying` when using the Core Animation rendering engine, and `.pauseAndRestore` when using the Main Thread rendering engine. Options: : **stop**: Stop the animation and reset it to the beginning of its current play time. The completion block is called. : **pause**: Pause the animation in its current state. The completion block is called. -: **pauseAndRestore**: Pause the animation and restart it when the application moves back to the foreground. The completion block is stored and called when the animation completes. -# -#### Loop Mode +: **pauseAndRestore**: Pause the animation and restart it when the application moves back to the foreground. The completion block is stored and called when the animation completes. This is the default when using the Main Thread rendering engine. +: **continuePlaying**: The animation continues playing in the background. This is the default when using the Core Animation rendering engine. + +### Loop Mode ```swift -var AnimationView.loopMode: LottieLoopMode { get set } +var LottieAnimationView.loopMode: LottieLoopMode { get set } ``` Sets the loop behavior for `play` calls. Defaults to `playOnce` Options: -: **playOnce**: Animation is played once then stops. -: **loop**: Animation will loop from end to beginning until stopped. -: **autoReverse**: Animation will play forward, then backwards and loop until stopped. -: **repeat(amount)**: Animation will loop from end to beginning up to *amount* of times. -: **repeatBackwards(amount)**: Animation will play forward, then backwards a *amount* of times. -# -#### Is Animation Playing +: **playOnce**: LottieAnimation is played once then stops. +: **loop**: LottieAnimation will loop from end to beginning until stopped. +: **autoReverse**: LottieAnimation will play forward, then backwards and loop until stopped. +: **repeat(amount)**: LottieAnimation will loop from end to beginning up to *amount* of times. +: **repeatBackwards(amount)**: LottieAnimation will play forward, then backwards a *amount* of times. + +### Is LottieAnimation Playing ```swift -var AnimationView.isAnimationPlaying: Bool { get set } +var LottieAnimationView.isAnimationPlaying: Bool { get set } ``` Returns `true` if the animation is currently playing, `false` if it is not. -# -#### Should Rasterize When Idle + +### Should Rasterize When Idle ```swift -var AnimationView.shouldRasterizeWhenIdle: Bool { get set } +var LottieAnimationView.shouldRasterizeWhenIdle: Bool { get set } ``` -When `true` the animation view will rasterize its contents when not animating. Rasterizing will improve performance of static animations. +When `true` the animation view will rasterize its contents when not animating. Rasterizing will improve performance of static animations. This may be required to avoid unexpected artifacts if your `LottieAnimationView` is not opaque with `alpha = 1.0` (e.g. if applying a crossfade to your view). ==Note:== this will not produce crisp results at resolutions above the animation's natural resolution. Defaults to `false` -# -#### Respect Animation Frame Rate + +### Respect LottieAnimation Frame Rate ```swift -var AnimationView.respectAnimationFrameRate: Bool { get set } +var LottieAnimationView.respectAnimationFrameRate: Bool { get set } ``` -When `true` the animation will play back at the framerate encoded in the `Animation` model. When `false` the animation will play at the framerate of the device. +When `true` the animation will play back at the framerate encoded in the `LottieAnimation` model. When `false` the animation will play at the framerate of the device. Defaults to `false` -# -#### Animation Speed + +### LottieAnimation Speed ```swift -var AnimationView.animationSpeed: CGFloat { get set } +var LottieAnimationView.animationSpeed: CGFloat { get set } ``` Sets the speed of the animation playback. Higher speed equals faster time. Defaults to `1` # -#### Current Progress +### Current Progress ```swift -var AnimationView.currentProgress: AnimationProgressTime { get set } +var LottieAnimationView.currentProgress: AnimationProgressTime { get set } + +// SwiftUI LottieView API: setting current progress +LottieView(animation: myAnimation) + .currentProgress(0.5) + +// SwiftUI LottieView API: getting current progress +LottieView(animation: myAnimation) + .playing() + .getRealtimeAnimationProgress($progressBinding) ``` Sets the current animation time with a Progress Time. Returns the current Progress Time, or the final Progress Time if an animation is in progress. ==Note==: Setting this will stop the current animation, if any. -# -#### Current Time + +### Current Time ```swift -var AnimationView.currentTime: TimeInterval { get set } +var LottieAnimationView.currentTime: TimeInterval { get set } + +// SwiftUI LottieView API +LottieView(animation: myAnimation) + .currentTime(4.0) ``` Sets the current animation time with a TimeInterval. Returns the current TimeInterval, or the final TimeInterval if an animation is in progress. ==Note==: Setting this will stop the current animation, if any. -# -#### Current Frame + +### Current Frame ```swift -var AnimationView.currentFrame: AnimationFrameTime { get set } +var LottieAnimationView.currentFrame: AnimationFrameTime { get set } + +// SwiftUI LottieView API +LottieView(animation: myAnimation) + .currentFrame(120.0) ``` Sets the current animation time with a Frame Time. Returns the current Frame Time, or the final Frame Time if an animation is in progress. ==Note==: Setting this will stop the current animation, if any. -# -#### Realtime Frame -```swift -var AnimationView.realtimeAnimationFrame: AnimationFrameTime { get } -``` -Returns the realtime Frame Time of an AnimationView while an animation is in flight. -# -#### Realtime Progress + +### Realtime Frame ```swift -var AnimationView.realtimeAnimationProgress: AnimationProgressTime { get } +var LottieAnimationView.realtimeAnimationFrame: AnimationFrameTime { get } ``` -Returns the realtime Progress Time of an AnimationView while an animation is in flight. -# -#### Force Display Update +Returns the realtime Frame Time of an LottieAnimationView while an animation is in flight. +ress ```swift -func AnimationView.forceDisplayUpdate() +var LottieAnimationView.realtimeAnimationProgress: AnimationProgressTime { get } ``` -Forces the AnimationView to redraw its contents. +Returns the realtime Progress Time of an LottieAnimationView while an animation is in flight. -# -### Using Markers + +## Using Markers Markers are a way to describe a point in time by a key name. Markers are encoded into animation JSON. By using markers a designer can mark playback points for a developer to use without having to worry about keeping track of animation frames. If the animation file is updated, the developer does not need to update playback code. -Markers can be used to [playback sections of animation](#play-with-marker-names), or can be read directly for more advanced use. Both `Animation` and `AnimationView` have methods for reading Marker Times. +Markers can be used to [playback sections of animation](#play-with-marker-names), or can be read directly for more advanced use. Both `LottieAnimation` and `LottieAnimationView` have methods for reading Marker Times. -# -#### Reading Marker Time +### Reading Marker Time ```swift -/// Animation View Methods -AnimationView.progressTime(forMarker named: String) -> AnimationProgressTime? -AnimationView.frameTime(forMarker named: String) -> AnimationFrameTime? -/// Animation Model Methods -Animation.progressTime(forMarker named: String) -> AnimationProgressTime? -Animation.frameTime(forMarker named: String) -> AnimationFrameTime? +/// LottieAnimation View Methods +LottieAnimationView.progressTime(forMarker named: String) -> AnimationProgressTime? +LottieAnimationView.frameTime(forMarker named: String) -> AnimationFrameTime? +/// LottieAnimation Model Methods +LottieAnimation.progressTime(forMarker named: String) -> AnimationProgressTime? +LottieAnimation.frameTime(forMarker named: String) -> AnimationFrameTime? ``` Each method returns the time for the marker specified by name. Returns nil if the marker is not found. -# -### Dynamic Animation Properties -Nearly all properties of a Lottie animation can be changed at runtime using a combination of [Animation Keypaths](#animation-keypaths) and [Value Providers](#value-providers). Setting a ValueProvider on a keypath will cause the animation to update its contents and read the new Value Provider. -In addition, animation properties can be read using `Animation Keypaths`. -# -#### Setting Dynamic Properties +## Dynamic LottieAnimation Properties +Nearly all properties of a Lottie animation can be changed at runtime using a combination of [LottieAnimation Keypaths](#animation-keypaths) and [Value Providers](#value-providers). Setting a ValueProvider on a keypath will cause the animation to update its contents and read the new Value Provider. +In addition, animation properties can be read using `LottieAnimation Keypaths`. + +### Setting Dynamic Properties ```swift -AnimationView.setValueProvider(_ valueProvider: AnyValueProvider, keypath: AnimationKeypath) +LottieAnimationView.setValueProvider(_ valueProvider: AnyValueProvider, keypath: AnimationKeypath) ``` Sets a ValueProvider for the specified keypath. The value provider will be set on all properties that match the keypath. @@ -415,16 +474,23 @@ Example: let fillKeypath = AnimationKeypath(keypath: "**.Fill 1.Color") /// A Color Value provider that returns a reddish color. let redValueProvider = ColorValueProvider(Color(r: 1, g: 0.2, b: 0.3, a: 1)) + /// Set the provider on the animationView. animationView.setValueProvider(redValueProvider, keypath: fillKeypath) + +// SwiftUI LottieView API +LottieView(animation: myAnimation) + .playing() + .valueProvider(redValueProvider, for: fillKeypath) ``` -# -#### Reading Animation Properties + +### Reading LottieAnimation Properties ```swift -AnimationView.getValue(for keypath: AnimationKeypath, atFrame: AnimationFrameTime?) -> Any? +LottieAnimationView.getValue(for keypath: AnimationKeypath, atFrame: AnimationFrameTime?) -> Any? ``` Reads the value of a property specified by the Keypath. Returns nil if no property is found. +Only supported by the Main Thread rendering engine. Parameters : **for**: The keypath used to search for the property. @@ -437,90 +503,45 @@ let fillKeypath = AnimationKeypath(keypath: "Layer 1.Group 1.Transform.Position" let position = animationView.getValue(for: fillKeypath, atFrame: nil) /// Returns Vector(10, 10, 0) for currentFrame. ``` -# -#### Logging Keypaths + +### Logging Keypaths ```swift -AnimationView.logHierarchyKeypaths() +// UIKit LottieAnimationView API +LottieAnimationView.logHierarchyKeypaths() + +// SwiftUI LottieView API +LottieView(animation: myAnimation) + .playing() + .configure { lottieAnimationView in + lottieAnimationView.logHierarchyKeypaths() + } ``` Logs all child keypaths of the animation into the console. -# -#### Adding Views to Animations -Custom views can be added to AnimationViews. These views will animate alongside the animation. - -# -#### Enabling and Disabling Animation Nodes +# Rendering Engines -`public func setNodeIsEnabled(isEnabled: Bool, keypath: AnimationKeypath)` +Lottie for iOS includes two rendering engine implementations, which are responsible for actually displaying and rendering Lottie animations: -Sets the enabled state of all animator nodes found with the keypath search. -This can be used to interactively enable / disable parts of the animation. -An enabled node affects the render tree, a disabled node will be removed from the render tree. + - The Core Animation rendering engine (enabled by default in Lottie 4.0+) uses Core Animation `CAAnimation`s to deliver better performance than the older Main Thread rendering engine. + - The Main Thread rendering engine (the default before Lottie 4.0) runs code on the main thread once per frame to update and re-render the animation. -- Parameter isEnabled: When true the animator nodes affect the rendering tree. When false the node is removed from the tree. -- Parameter keypath: The keypath used to find the node(s). +You can learn more about the Core Animation rendering engine in [this post](https://medium.com/airbnb-engineering/announcing-lottie-4-0-for-ios-d4d226862a54) on Airbnb's Tech Blog: **[Announcing Lottie 4.0 for iOS](https://medium.com/airbnb-engineering/announcing-lottie-4-0-for-ios-d4d226862a54)**. -Example -```swift -// Create an animation view. -let animation = Animation.named("LottieLogo1", subdirectory: "TestAnimations") -// Some time later. Create a keypath to find any node named "Stroke 1" -let keypath1 = AnimationKeypath(keypath: "**.Stroke 1") -// Disable all nodes named Stroke 1, removing them from the current render tree. -animationView.setNodeIsEnabled(isEnabled: false, keypath: keypath1) -// Re-enable all nodes named Stroke 1. -animationView.setNodeIsEnabled(isEnabled: true, keypath: keypath1) -``` - -# -#### Adding Subviews -```swift -AnimationView.addSubview(_ subview: AnimationSubview, forLayerAt keypath: AnimationKeypath) -``` -Searches for the nearest child layer to the first Keypath and adds the subview to that layer. The subview will move and animate with the child layer. Furthermore the subview will be in the child layers coordinate space. -==Note==: if no layer is found for the keypath, then nothing happens. +The Core Animation rendering engine and Main Thread rendering engine support different sets of functionality. A complete list of supported functionality is available [here](https://airbnb.io/lottie/#/supported-features). -Parameters -: **subview**: The subview to add to the found animation layer. -: **keypath**: The keypath used to find the animation layer. +Most animations are rendered exactly the same by both rendering engines, but as shown above the Core Animation rendering engine and Main Thread rendering engine support slightly different sets of functionality. -Example: -```swift -/// A keypath that finds `Layer 1` -let layerKeypath = AnimationKeypath(keypath: "Layer 1") +As of [Lottie 4.0](https://medium.com/airbnb-engineering/announcing-lottie-4-0-for-ios-d4d226862a54), Lottie uses the Core Animation rendering engine by default. If Lottie detects that an animation uses functionality not supported by the Core Animation rendering engine, it will automatically fall back to the Main Thread rendering engine. You can also configure which rendering engine is used by configuring the `LottieConfiguration.renderingEngine`. -/// Wrap the custom view in an `AnimationSubview` -let subview = AnimationSubview() -subview.addSubview(customView) -/// Set the provider on the animationView. -animationView.addSubview(subview, forLayerAt: layerKeypath) -``` -# -#### Converting CGRect and CGPoint to Layers -```swift -/// Converts a rect -AnimationView.convert(_ rect: CGRect, toLayerAt keypath: AnimationKeypath) -> CGRect? -/// Converts a point -AnimationView.convert(_ point: CGPoint, toLayerAt keypath: AnimationKeypath) -> CGPoint? -``` -These two methods are used to convert geometry from the AnimationView's coordinate space into the coordinate space of the layer found at Keypath. +# Image Provider +Image provider is a protocol that is used to supply images to `LottieAnimationView`. -If no layer is found, nil is returned - -Parameters -: **point or rect**: The CGPoint or CGRect in the AnimationView's coordinate space to convert. -: **keypath**: The keypath used to find the layer. -# -[Back to contents](#contents) -## Image Provider -Image provider is a protocol that is used to supply images to `AnimationView`. - -Some animations require a reference to an image. The image provider loads and provides those images to the `AnimationView`. Lottie includes a couple of prebuilt Image Providers that supply images from a Bundle, or from a FilePath. +Some animations require a reference to an image. The image provider loads and provides those images to the `LottieAnimationView`. Lottie includes a couple of prebuilt Image Providers that supply images from a Bundle, or from a FilePath. Additionally custom Image Providers can be made to load images from a URL, or to Cache images. -### BundleImageProvider +## BundleImageProvider ```swift public class BundleImageProvider: AnimationImageProvider ``` @@ -532,8 +553,8 @@ let imageProvider = BundleImageProvider(bundle: Bundle.main, searchPath: "Animat /// Set the provider on an animation. animationView.imageProvider = imageProvider ``` -# -### FilepathImageProvider + +## FilepathImageProvider ```swift public class FilepathImageProvider: AnimationImageProvider ``` @@ -545,42 +566,42 @@ let imageProvider = AnimationImageProvider(filepath: url) /// Set the provider on an animation. animationView.imageProvider = imageProvider ``` -[Back to contents](#contents) -## Animation Cache -`AnimationCacheProvider` is a protocol that describes an Animation Cache. Animation Cache is used when loading `Animation` models. Using an Animation Cache can increase performance when loading an animation multiple times. +# LottieAnimation Cache -Lottie comes with a prebuilt LRU Animation Cache. +`AnimationCacheProvider` is a protocol that describes an LottieAnimation Cache. LottieAnimation Cache is used when loading `LottieAnimation` models. Using an LottieAnimation Cache can increase performance when loading an animation multiple times. -### LRUAnimationCache -An Animation Cache that will store animations up to `cacheSize`. Once `cacheSize` is reached, the least recently used animation will be ejected. The default size of the cache is 100. +Lottie comes with a prebuilt LRU LottieAnimation Cache. + +## LRUAnimationCache +An LottieAnimation Cache that will store animations up to `cacheSize`. Once `cacheSize` is reached, the least recently used animation will be ejected. The default size of the cache is 100. LRUAnimationCache has a global `sharedCache` that is used to store the animations. You may also call `LRUAnimationCache.sharedCache.clearCache()` to clear the cache. -[Back to contents](#contents) -## Value Providers -`AnyValueProvider` is a protocol that return animation data for a property at a given time. Every fame an `AnimationView` queries all of its properties and asks if their ValueProvider has an update. If it does the AnimationView will read the property and update that portion of the animation. + +# Value Providers +`AnyValueProvider` is a protocol that return animation data for a property at a given time. Every fame an `LottieAnimationView` queries all of its properties and asks if their ValueProvider has an update. If it does the LottieAnimationView will read the property and update that portion of the animation. Value Providers can be used to dynamically set animation properties at run time. -### Primitives +## Primitives ValueProviders work with a few Primitive data types. - - **Color**: A primitive that describes a color in R G B A (0-1) - - **Vector1D**: A single float value. - - **Vector3D**: A three dimensional vector. (X, Y, Z) + - **LottieColor**: A primitive that describes a color in R G B A (0-1) + - **LottieVector1D**: A single float value. + - **LottieVector3D**: A three dimensional vector. (X, Y, Z) -### Prebuilt Providers +## Prebuilt Providers Lottie comes with a handful of prebuilt providers for each Primitive Type. Each Provider can be initialized with a single value, or a block that will be called on a frame-by-frame basis. Example ```swift /// A Color Value provider that returns a reddish color. -let redValueProvider = ColorValueProvider(Color(r: 1, g: 0.2, b: 0.3, a: 1)) +let redValueProvider = ColorValueProvider(LottieColor(r: 1, g: 0.2, b: 0.3, a: 1)) /// A keypath that finds the color value for all `Fill 1` nodes. let fillKeypath = AnimationKeypath(keypath: "**.Fill 1.Color") @@ -589,13 +610,12 @@ animationView.setValueProvider(redValueProvider, keypath: fillKeypath) /// Later... /// Changing the value provider will update the animation. -redValueProvider.color = Color(r: 0, g: 0.2, b: 1, a: 1) +redValueProvider.color = LottieColor(r: 0, g: 0.2, b: 1, a: 1) ``` -[Back to contents](#contents) -## Animation Keypaths -`AnimationKeypath` is an object that describes a keypath search for nodes in the animation JSON. `AnimationKeypath` matches views and properties inside of `AnimationView` to their backing `Animation` model by name. +# LottieAnimation Keypaths +`AnimationKeypath` is an object that describes a keypath search for nodes in the animation JSON. `AnimationKeypath` matches views and properties inside of `LottieAnimationView` to their backing `LottieAnimation` model by name. -A keypath can be used to set properties on an existing animation, or can be validated with an existing `Animation`. `AnimationKeypath` can describe a specific object, or can use wildcards for fuzzy matching of objects. Acceptable wildcards are either "*" (star) or "**" (double star). Single star will search a single depth for the next object. Double star will search any depth. +A keypath can be used to set properties on an existing animation, or can be validated with an existing `LottieAnimation`. `AnimationKeypath` can describe a specific object, or can use wildcards for fuzzy matching of objects. Acceptable wildcards are either "*" (star) or "**" (double star). Single star will search a single depth for the next object. Double star will search any depth. An `AnimationKeypath` can be initialized with a dot-separated keypath, or with an array of keys. @@ -615,8 +635,7 @@ Code Example: let fillKeypath = AnimationKeypath(keypath: "**.Fill 1.Color") ``` -[Back to contents](#contents) -## Animated Control +# Animated Control Lottie comes prepacked with a two Animated Controls, `AnimatedSwitch` and `AnimatedButton`. Both of these controls are built on top of `AnimatedControl` `AnimatedControl` is a subclass of `UIControl` that provides an interactive mechanism for controlling the visual state of an animation in response to user actions. @@ -625,8 +644,9 @@ The `AnimatedControl` will show and hide layers depending on the current `UICont Users of `AnimationControl` can set a Layer Name for each `UIControl.State`. When the state is change the `AnimationControl` will change the visibility of its layers. -[Back to contents](#contents) -## Animated Switch +# Animated Switch + +Also available as `LottieSwitch`, a SwiftUI `View` implementation. ![SwitchButton](images/switchTest.gif) @@ -641,8 +661,11 @@ public func setProgressForState(fromProgress: AnimationProgressTime, toProgress: AnimationProgressTime, forState onState: Bool) ``` -[Back to contents](#contents) -## Animated Button + +# Animated Button + +Also available as `LottieButton`, a SwiftUI `View` implementation. + ![HeartButton](images/HeartButton.gif) An interactive button that plays an animation when pressed. @@ -665,7 +688,7 @@ Example: let twitterButton = AnimatedButton() twitterButton.translatesAutoresizingMaskIntoConstraints = false /// Set an animation on the button. -twitterButton.animation = Animation.named("TwitterHeartButton", subdirectory: "TestAnimations") +twitterButton.animation = LottieAnimation.named("TwitterHeartButton", subdirectory: "TestAnimations") /// Turn off clips to bounds, as the animation goes outside of the bounds. twitterButton.clipsToBounds = false /// Set animation play ranges for touch states @@ -674,37 +697,37 @@ twitterButton.setPlayRange(fromMarker: "touchDownEnd", toMarker: "touchUpCancel" twitterButton.setPlayRange(fromMarker: "touchDownEnd", toMarker: "touchUpEnd", event: .touchUpInside) view.addSubview(twitterButton) ``` -[Back to contents](#contents) -## Examples -### Changing Animations at Runtime +# Examples + +## Changing Animations at Runtime Lottie can do more than just play beautiful animations. Lottie allows you to **change** animations at runtime. -### Say we want to create 4 toggle switches. +## Say we want to create 4 toggle switches. ![Toggle](images/switch_Normal.gif) It's easy to create the four switches and play them: ```swift -let animationView = AnimationView(name: "toggle"); +let animationView = LottieAnimationView(name: "toggle"); self.view.addSubview(animationView) animationView.play() -let animationView2 = AnimationView(name: "toggle"); +let animationView2 = LottieAnimationView(name: "toggle"); self.view.addSubview(animationView2) animationView2.play() -let animationView3 = AnimationView(name: "toggle"); +let animationView3 = LottieAnimationView(name: "toggle"); self.view.addSubview(animationView3) animationView3.play() -let animationView4 = AnimationView(name: "toggle"); +let animationView4 = LottieAnimationView(name: "toggle"); self.view.addSubview(animationView4) animationView4.play() ``` -### Now lets change their colors +## Now lets change their colors ![Recolored Toggle](images/switch_BgColors.gif) ```swift @@ -726,128 +749,33 @@ animationView3.setValueProvider(redValueProvider, keypath: keypath) animationView4.setValueProvider(orangeValueProvider, keypath: keypath) ``` The keyPath is a dot separated path of layer and property names from After Effects. -AnimationView provides `func logHierarchyKeypaths()` which will recursively log all settable keypaths for the animation. +LottieAnimationView provides `func logHierarchyKeypaths()` which will recursively log all settable keypaths for the animation. ![Key Path](images/aftereffectskeypath.png) "BG-On.Group 1.Fill 1.Color" -### Now lets change a couple of properties +## Now lets change a couple of properties ![Multiple Colors](images/switch_MultipleBgs.gif) Lottie allows you to change **any** property that is animatable in After Effects. -[Back to contents](#contents) - -# -## Supported After Effects Features - -See Supported Features by platform [here](/supported-features.md) -| **Shapes** | **2.5.2** | **3.0** | -|:--|:-:|:-:| -| Shape | ๐Ÿ‘ | ๐Ÿ‘ | -| Ellipse | ๐Ÿ‘ | ๐Ÿ‘ | -| Rectangle | ๐Ÿ‘ | ๐Ÿ‘ | -| Rounded Rectangle | ๐Ÿ‘ | ๐Ÿ‘ | -| Polystar | ๐Ÿ‘ | ๐Ÿ‘ | -| Group | ๐Ÿ‘ | ๐Ÿ‘ | -| Repeater | ๐Ÿ‘ | โ›”๏ธ | -| Trim Path (individually) | โ›”๏ธ | ๐ŸŽ‰ | -| Trim Path (simultaneously) | โ—๏ธ | ๐ŸŽ‰ | -| **Renderable** | **2.5.2** | **3.0** | -| Fill | ๐Ÿ‘ | ๐Ÿ‘ | -| Stroke | ๐Ÿ‘ | ๐Ÿ‘ | -| Radial Gradient | ๐Ÿ‘ | ๐Ÿ‘ | -| Linear Gradient | ๐Ÿ‘ | ๐Ÿ‘ | -| Gradient Stroke | โ›”๏ธ | ๐ŸŽ‰ | -| **Transforms** | **2.5.2** | **3.0** | -| Position | ๐Ÿ‘ | ๐Ÿ‘ | -| Position (separated X/Y) | โ—๏ธ | ๐Ÿ‘ | -| Scale | ๐Ÿ‘ | ๐Ÿ‘ | -| Skew | โ›”๏ธ | ๐ŸŽ‰ | -| Rotation | ๐Ÿ‘ | ๐Ÿ‘ | -| Anchor Point | ๐Ÿ‘ | ๐Ÿ‘ | -| Opacity | ๐Ÿ‘ | ๐Ÿ‘ | -| Parenting | ๐Ÿ‘ | ๐Ÿ‘ | -| Auto Orient | โ›”๏ธ | โ›”๏ธ | -| **Interpolation** | **2.5.2** | **3.0** | -| Linear Interpolation | โ—๏ธ | ๐ŸŽ‰ | -| Bezier Interpolation | ๐Ÿ‘ | ๐Ÿ‘ | -| Hold Interpolation | ๐Ÿ‘ | ๐Ÿ‘ | -| Spatial Bezier Interpolation | โ—๏ธ | ๐ŸŽ‰ | -| Rove Across Time | ๐Ÿ‘ | ๐Ÿ‘ | -| **Masks** | **2.5.2** | **3.0** | -| Mask Path | ๐Ÿ‘ | ๐Ÿ‘ | -| Mask Opacity | ๐Ÿ‘ | ๐Ÿ‘ | -| Add | ๐Ÿ‘ | ๐Ÿ‘ | -| Subtract | โ—๏ธ | ๐ŸŽ‰ | -| Intersect | โ›”๏ธ | ๐ŸŽ‰ | -| Lighten | โ›”๏ธ | โ›”๏ธ | -| Darken | โ›”๏ธ | โ›”๏ธ | -| Difference | โ›”๏ธ | โ›”๏ธ | -| Expansion | โ›”๏ธ | โ›”๏ธ | -| Feather | โ›”๏ธ | โ›”๏ธ | -| **Mattes** | **2.5.2** | **3.0** | -| Alpha Matte | ๐Ÿ‘ | ๐Ÿ‘ | -| Alpha Inverted Matte | โ›”๏ธ | ๐ŸŽ‰ | -| Luma Matte | โ›”๏ธ | โ›”๏ธ | -| Luma Inverted Matte | โ›”๏ธ | โ›”๏ธ | -| **Merge Paths** | **2.5.2** | **3.0** | -| Merge | โ›” | โ›” | -| Add | โ›” | โ›” | -| Subtract | โ›” | โ›” | -| Intersect | โ›” | โ›” | -| Exclude Intersection | โ›” | โ›” | -| **Layer Effects** | **2.5.2** | **3.0** | -| Fill | โ›”๏ธ | โ›”๏ธ | -| Stroke | โ›”๏ธ | โ›”๏ธ | -| Tint | โ›”๏ธ | โ›”๏ธ | -| Tritone | โ›”๏ธ | โ›”๏ธ | -| Levels Individual Controls | โ›”๏ธ | โ›”๏ธ | -| **Text** | **2.5.2** | **3.0** | -| Glyphs | โ›”๏ธ | โ›”๏ธ | -| Fonts | โ›”๏ธ | ๐ŸŽ‰ | -| Transform | โ›”๏ธ |๐ŸŽ‰ | -| Fill | โ›”๏ธ | ๐ŸŽ‰ | -| Stroke | โ›”๏ธ | ๐ŸŽ‰ | -| Tracking | โ›”๏ธ | ๐ŸŽ‰ | -| Anchor point grouping | โ›”๏ธ | โ›”๏ธ | -| Text Path | โ›” | โ›”๏ธ | -| Per-character 3D | โ›” | โ›”๏ธ | -| Range selector (Units) | โ›” | โ›”๏ธ | -| Range selector (Based on) | โ›” | โ›”๏ธ | -| Range selector (Amount) | โ›” | โ›”๏ธ | -| Range selector (Shape) | โ›” | โ›”๏ธ | -| Range selector (Ease High) | โ›” | โ›”๏ธ | -| Range selector (Ease Low) | โ›” | โ›”๏ธ | -| Range selector (Randomize order) | โ›” | โ›”๏ธ | -| expression selector | โ›” | โ›”๏ธ | -| **Other** | **2.5.2** | **3.0** | -| Expressions | โ›”๏ธ | โ›”๏ธ | -| Images | ๐Ÿ‘ | ๐Ÿ‘ | -| Precomps | ๐Ÿ‘ | ๐Ÿ‘ | -| Time Stretch | โ›”๏ธ | ๐Ÿ‘ | -| Time remap | โ›”๏ธ | ๐Ÿ‘ | -| Markers | โ›”๏ธ | ๐ŸŽ‰ | - -[Back to contents](#contents) -## Alternatives +# Alternatives 1. Build animations by hand. Building animations by hand is a huge time commitment for design and engineering across Android and iOS. It's often hard or even impossible to justify spending so much time to get an animation right. 2. [Facebook Keyframes](https://github.com/facebookincubator/Keyframes). Keyframes is a wonderful new library from Facebook that they built for reactions. However, Keyframes doesn't support some of Lottie's features such as masks, mattes, trim paths, dash patterns, and more. 2. Gifs. Gifs are more than double the size of a bodymovin JSON and are rendered at a fixed size that can't be scaled up to match large and high density screens. 3. Png sequences. Png sequences are even worse than gifs in that their file sizes are often 30-50x the size of the bodymovin json and also can't be scaled up. -[Back to contents](#contents) -## Why is it Called Lottie? +# Why is it Called Lottie? Lottie is named after a German film director and the foremost pioneer of silhouette animation. Her best known films are The Adventures of Prince Achmed (1926) โ€“ the oldest surviving feature-length animated film, preceding Walt Disney's feature-length Snow White and the Seven Dwarfs (1937) by over ten years. [The art of Lotte Reineger](https://www.youtube.com/watch?v=LvU55CUw5Ck&feature=youtu.be) -[Back to contents](#contents) -## Contributing -Contributors are more than welcome. Just upload a PR with a description of your changes. -To get ramped up on how Lottie-iOS works, read through the [Contributor Documentation](/ios-contributor.md) +# Contributing +Contributors are more than welcome. Just post a PR with a description of your changes. For larger changes, please open a discussion first to help build alignment on the necessary changes and the design direction. + +# Issues or Feature Requests? + +Use GitHub issues for for filing bug reports about crashes, regressions, unexpected behavior, etc. Be sure to check the [list of supported features](https://airbnb.io/lottie/#/supported-features) before submitting. If an animation is not working, please attach the After Effects file or animation JSON file to your issue. -[Back to contents](#contents) -## Issues or Feature Requests? -File github issues for anything that is broken. Be sure to check the [list of supported features](#supported-after-effects-features) before submitting. If an animation is not working, please attach the After Effects file to your issue. Debugging without the original can be very difficult. Lottie is developed and maintained by [Brandon Withrow](mailto:brandon@withrow.io). Feel free to reach out via [email](mailto:brandon@withrow.io) or [Twitter](https://twitter.com/theWithra) +If you have a question or feature request, please start a discussion here: +https://github.com/airbnb/lottie-ios/discussions -[Back to contents](#contents) diff --git a/other-platforms.md b/other-platforms.md index 1fb13dd..e4592ca 100644 --- a/other-platforms.md +++ b/other-platforms.md @@ -4,9 +4,12 @@ The Lottie community has build Lottie bindings for the following platforms: # Wrappers * [Xamarin](https://github.com/martijn00/LottieXamarin) * [NativeScript](https://github.com/bradmartin/nativescript-lottie) -* [Axway Appcelerator](https://github.com/m1ga/ti.animation) +* [Titanium SDK](https://github.com/m1ga/ti.animation) * [Qt QML](https://sea-region.github.com/kbroulik/lottie-qml) * [Rlottie](https://github.com/Samsung/rlottie) +* [Python](https://gitlab.com/mattia.basaglia/python-lottie) +* [MIT Appinventor](https://community.appinventor.mit.edu/t/lottie-animations-add-cool-animations-to-your-apps/44483/) +* [Flutter](https://github.com/xvrh/lottie-flutter) # Web * [React](https://github.com/chenqingspring/react-lottie) @@ -17,4 +20,4 @@ The Lottie community has build Lottie bindings for the following platforms: # Operating Systems * [Windows](https://github.com/windows-toolkit/Lottie-Windows) * [Qt](https://blog.qt.io/blog/2019/03/08/announcing-qtlottie/) -* [Skia](https://skia.org/user/modules/skottie) \ No newline at end of file +* [Skia](https://skia.org/user/modules/skottie) diff --git a/react-native.md b/react-native.md index 53930fc..58413a8 100644 --- a/react-native.md +++ b/react-native.md @@ -1,251 +1,281 @@ -# Getting Started +# Lottie React Native -Get started with Lottie by installing the node module with yarn or npm: +[![npm Version](https://img.shields.io/npm/v/lottie-react-native.svg)](https://www.npmjs.com/package/lottie-react-native) [![License](https://img.shields.io/npm/l/lottie-react-native.svg)](https://www.npmjs.com/package/lottie-react-native) -
yarn add lottie-react-native@{{ book.reactNativeVersion }}
-# or
-npm i --save lottie-react-native@{{ book.reactNativeVersion }}
-
+Lottie component for React Native ([Repo](https://github.com/lottie-react-native/lottie-react-native)) -### iOS +# Installing -If you're using CocoaPods on iOS, you can put the following in your `Podfile`: +## Breaking Changes in v6! + +We've made some significant updates in version 6 that may impact your current setup. To get all the details about these changes, check out the [migration guide](https://github.com/lottie-react-native/lottie-react-native/blob/master/MIGRATION-5-TO-6.md). + +Stay informed to ensure a seamless transition to the latest version. Thank you! + +## iOS and Android + +- Install `lottie-react-native` (latest): -```ruby -pod 'lottie-ios', :path => '../node_modules/lottie-ios' -pod 'lottie-react-native', :path => '../node_modules/lottie-react-native' +``` +yarn add lottie-react-native ``` -If you're not using CocoaPods on iOS, you can use `react-native link`: +Go to your ios folder and run: -```bash -react-native link lottie-ios -react-native link lottie-react-native ``` +pod install +``` + +## Web -After this, open the Xcode project configuration and add the `Lottie.framework` as `Embedded -Binaries`. +- Install `lottie-react-native` (latest): -### Android +``` +yarn add lottie-react-native +``` -For android, you can `react-native link` as well: +- Add dependencies for web players: -```bash -react-native link lottie-react-native +``` +yarn add @dotlottie/react-player @lottiefiles/react-lottie-player ``` -or you can add it manually: +## Windows (React Native >= 0.63) -`settings.gradle`: +
+Install the `lottie-react-native` npm package. (Click to expand) +
+ +Add the following to the end of your project file. For C# apps, this should come after any `Microsoft.Windows.UI.Xaml.CSharp.targets` includes. For C++ apps, it should come after any `Microsoft.Cpp.targets` includes. +```xml + + $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\lottie-react-native\package.json'))\node_modules\lottie-react-native + + + + +``` -

-include ':lottie-react-native'
-project(':lottie-react-native').projectDir = new File(rootProject.projectDir, '../node_modules/lottie-react-native/src/android')
-
+Add the LottieReactNative.vcxproj file to your Visual Studio solution to ensure it takes part in the build. -`build.gradle`: +For C# apps, you'll need to install the following packages through NuGet: -

-dependencies {
-  ...
-  compile project(':lottie-react-native')
-  ...
-}
-
+- LottieGen.MsBuild +- Microsoft.UI.Xaml +- Win2D.uwp +- Microsoft.Toolkit.Uwp.UI.Lottie + - This package is used for loading JSON dynamically. If you only need codegen animation, you can set `false` in your project file and omit this reference. + +For C++ apps, you'll need these NuGet packages: + +- LottieGen.MsBuild +- Microsoft.UI.Xaml + +WinUI 2.6 (Microsoft.UI.Xaml 2.6.0) is required by default. Overriding this requires creating a Directory.Build.props file in your project root with a `` property. -Lottie requires Android support library version 26. If you're using the `react-native init` -template, you may still be using 23. To change this, simply go to `android/app/build.gradle` and -find the `compileSdkVersion` option inside of the `android` block and change it to +In your application code where you set up your React Native Windows PackageProviders list, add the LottieReactNative provider: +```csharp +// C# +PackageProviders.Add(new LottieReactNative.ReactPackageProvider(new AnimatedVisuals.LottieCodegenSourceProvider())); ``` -android { - compileSdkVersion 26 // <-- update this to 26 - // ... + +```cpp +// C++ +#include +#include + +... + +PackageProviders().Append(winrt::LottieReactNative::ReactPackageProvider(winrt::AnimatedVisuals::LottieCodegenSourceProvider())); ``` -You must also add the `LottiePackage` to `getPackages()` in your `ReactApplication` +Codegen animations are supported by adding LottieAnimation items to your project file. These will be compiled into your application and available at runtime by name. For example: -```java - import com.airbnb.android.react.lottie.LottiePackage; - - ... - - @Override - protected List getPackages() { - return Arrays.asList( - ... - new LottiePackage() - ); - } - }; -``` - -Then, go to `android/build.gradle` and make sure it has : - -``` -allprojects { - repositories { - mavenLocal() - jcenter() - // Add the following 3 lines - maven { - url 'https://maven.google.com' - } - maven { - // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm - url "$rootDir/../node_modules/react-native/android" - } - } -} +```xml + + + + ``` -With this change you should be ready to go. +```js +// js + +``` -Lottie's animation progress can be controlled with an `Animated` value: +Codegen is available to both C# and C++ applications. Dynamic loading of JSON strings at runtime is currently only supported in C# applications. -```jsx -import React from 'react'; -import { Animated, Easing } from 'react-native'; -import LottieView from 'lottie-react-native'; - -export default class BasicExample extends React.Component { - constructor(props) { - super(props); - this.state = { - progress: new Animated.Value(0), - }; - } - - componentDidMount() { - Animated.timing(this.state.progress, { - toValue: 1, - duration: 5000, - easing: Easing.linear, - }).start(); - } +
+ +# Usage + +Lottie can be used in a declarative way: - render() { - return ( - - ); - } +```jsx +import React from "react"; +import LottieView from "lottie-react-native"; + +export default function Animation() { + return ( + + ); } ``` Additionally, there is an imperative API which is sometimes simpler. -```jsx -import React from 'react'; -import LottieView from 'lottie-react-native'; +```tsx +import React, { useEffect, useRef } from "react"; +import LottieView from "lottie-react-native"; + +export default function AnimationWithImperativeApi() { + const animationRef = useRef(null); + + useEffect(() => { + animationRef.current?.play(); -export default class BasicExample extends React.Component { - componentDidMount() { - this.animation.play(); // Or set a specific startFrame and endFrame with: - this.animation.play(30, 120); - } - - render() { - return ( - { - this.animation = animation; - }} - source={require('../path/to/animation.json')} - /> - ); - } + animationRef.current?.play(30, 120); + }, []); + + return ( + + ); } ``` -## Sample App - -You can check out the example project with the following instructions +Lottie's animation view can be controlled by either React Native Animated or Reanimated API. -1. Clone the repo: `git clone https://github.com/airbnb/lottie-react-native.git` -2. Open: `cd lottie-react-native` and Install: `npm install` -3. Run `npm start` to start the packager. ** The packager must be running to use the sample apps.** -4. In another CLI window, do the following: +```tsx +import React, { useEffect, useRef, Animated } from "react"; +import { Animated, Easing } from "react-native"; +import LottieView from "lottie-react-native"; -For Running iOS: +const AnimatedLottieView = Animated.createAnimatedComponent(LottieView); -1. If you don't have CocoaPods installed, run `bundle install` -2. Install pods: `npm run build:pods` -3. Run Example: `npm run run:ios` +export default function ControllingAnimationProgress() { + const animationProgress = useRef(new Animated.Value(0)); -For Running Android: + useEffect(() => { + Animated.timing(animationProgress.current, { + toValue: 1, + duration: 5000, + easing: Easing.linear, + useNativeDriver: false, + }).start(); + }, []); + + return ( + + ); +} +``` -1. Run Example: `npm run run:android` +Changing color of layers: -# Props +NOTE: This feature may not work properly on Android. We will try fix it soon. +```jsx +import React from "react"; +import LottieView from "lottie-react-native"; + +export default function ChangingColorOfLayers() { + return ( + + ); +} ``` -type AnimationProps = { - // The source of animation. Can be referenced as a local asset by a string, or remotely - // with an object with a `uri` property, or it can be an actual JS object of an - // animation, obtained (for example) with something like - // `require('../path/to/animation.json')` - source: string | AnimationJson | { uri: string }, - // A number between 0 and 1, or an `Animated` number between 0 and 1. This number - // represents the normalized progress of the animation. If you update this prop, the - // animation will correspondingly update to the frame at that progress value. This - // prop is not required if you are using the imperative API. - progress: number | Animated = 0, +# If you want to use `.lottie` files - // The speed the animation will progress. This only affects the imperative API. The - // default value is 1. - speed: number = 1, +You need to modify your `metro.config.js` file accordingly by adding `lottie` extension to the `assetExts` array: - // A boolean flag indicating whether or not the animation should loop. - loop: boolean = false, +```js +const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config"); - // Style attributes for the view, as expected in a standard `View`: - // http://facebook.github.io/react-native/releases/0.39/docs/view.html#style - // CAVEAT: border styling is not supported. - style?: ViewStyle, +const defaultConfig = getDefaultConfig(__dirname); - // [Android] Relative folder inside of assets containing image files to be animated. - // Make sure that the images that bodymovin export are in that folder with their names unchanged (should be img_#). - // Refer to https://github.com/airbnb/lottie-android#image-support for more details. - imageAssetsFolder: string, +/** + * Metro configuration + * https://facebook.github.io/metro/docs/configuration + * + * @type {import('metro-config').MetroConfig} + */ +const config = { + resolver: { + assetExts: [...defaultConfig.resolver.assetExts, "lottie"], + }, }; +module.exports = mergeConfig(getDefaultConfig(__dirname), config); ``` +# Setup jest for dotLottie files -Methods: +Create a file in the following path `__mocks__/lottieMock.js` and add the following code: +```js +module.exports = "lottie-test-file-stub"; ``` -class Animation extends React.Component { - - // play the animation all the way through, at the speed specified as a prop. - play(); +Then add the following to your `jest.config.js` file: - // Reset the animation back to `0` progress. - reset(); - +```js +module.exports = { + ... + moduleNameMapper: { + ..., + '\\.(lottie)$': '/jest/__mocks__/lottieMock.js', + }, + ... } ``` -# Troubleshooting - -If you are trying to run `pod install` and you get: +# API -``` -[!] Unable to find a specification for `lottie-ios` -``` +You can find the full list of props and methods available in our [API document](https://github.com/airbnb/lottie-react-native/blob/master/docs/api.md). These are the most common ones: -Run `pod repo update` and retry. +| Prop | Description | Default | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| **`source`** | **Mandatory** - The source of animation. Can be referenced as a local asset by a string, or remotely with an object with a `uri` property, or it can be an actual JS object of an animation, obtained (for example) with something like `require('../path/to/animation.json')`. | _None_ | +| **`style`** | Style attributes for the view, as expected in a standard [`View`](https://facebook.github.io/react-native/docs/layout-props.html). | You need to set it manually. Refer to this [pull request](https://github.com/lottie-react-native/lottie-react-native/pull/992). | +| **`loop`** | A boolean flag indicating whether or not the animation should loop. | `true` | +| **`autoPlay`** | A boolean flag indicating whether or not the animation should start automatically when mounted. This only affects the imperative API. | `false` | +| **`colorFilters`** | An array of objects denoting layers by KeyPath and a new color filter value (as hex string). | `[]` | -When your build fails with: +[More...](https://github.com/airbnb/lottie-react-native/blob/master/docs/api.md) -``` -LottieReactNative/LRNContainerView.h: 'Lottie/Lottie.h' file not found -``` +# Troubleshooting -Add the `Lottie.framework` to the `Embedded Binaries` in your Xcode project configuration. +Not all After Effects features are supported by Lottie. If you notice there are some layers or animations missing check [this list](https://github.com/airbnb/lottie/blob/master/supported-features.md) to ensure they are supported. -## Animation issues -Refer to the troubleshooting guilds on [Android](/android/troubleshooting.md) or [iOS](/ios/troubleshooting.md). \ No newline at end of file +For further troubleshooting, please refer to the [troubleshooting guide](https://github.com/lottie-react-native/lottie-react-native#troubleshooting). diff --git a/sponsorship.md b/sponsorship.md new file mode 100644 index 0000000..b89a007 --- /dev/null +++ b/sponsorship.md @@ -0,0 +1,17 @@ +# Sponsorship +Lottie is an open source project built and maintained by a single or very small group of people per platform. Almost all support and work is done on nights and weekends outside of any full time jobs. If you use Lottie and want to support its ongoing development, please considering having you or your company Sponsor Lottie. Each repo has a sponsorship section on the right side of the main repo with links to Open Collective or GitHub Sponsors. + +## Open Collective + +Lottie accepts sponsorship via [Open Collective](https://opencollective.com/lottie). + +## Why Sponsor Lottie? + +Lottie would not exist without thousands of hours of unpaid work on nights and weekends. Sponsoring Lottie ensures that all platforms continue to get the support and maintenance they need. + +## What Do You Get? + +Lots of stuff! The sponsorship tiers on GitHub Sponsors and Open Collective list the benefits of each tier. Some of the benefits include: +* Access to a Lottie Slack organization that has core contributors from all platforms. +* Prioritization for bugs, support, and feature requests. +* Inclusion on our README and documentation sites. diff --git a/supported-features.md b/supported-features.md index 01db77c..217bd06 100644 --- a/supported-features.md +++ b/supported-features.md @@ -1,97 +1,119 @@ # Supported Features -| **Shapes** | **Android** | **iOS** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | -|:--|:-:|:-:|:-:|:-:|:-:|:-:| -| Shape | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Ellipse | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Rectangle | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Rounded Rectangle | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Polystar | ๐Ÿ‘ | ๐Ÿ‘ | ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธโ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Group | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Repeater | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Trim Path (individually) | ๐Ÿ‘ | ๐Ÿ‘ | ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธโ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Trim Path (simultaneously) | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| **Fills** | **Android** | **iOS** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | -| Color | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Opacity | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Fill Rule | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Radial Gradient | ๐Ÿ‘ | ๐Ÿ‘ | ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Linear Gradient | ๐Ÿ‘ | ๐Ÿ‘ | ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| **Strokes** | **Android** | **iOS** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | -| Color | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Opacity | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Width | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Line Cap | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Line Join | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Miter Limit | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Dashes | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Gradient | ๐Ÿ‘ | ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๐Ÿ‘ | ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธโ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| **Transforms** | **Android** | **iOS** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | -| Position | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Position (separated X/Y) | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Scale | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Rotation | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Anchor Point | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Opacity | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Parenting | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Auto Orient | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Skew | โ“ | ๐Ÿ‘ | โ“ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| **Interpolation** | **Android** | **iOS** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | -| Linear Interpolation | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Bezier Interpolation | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Hold Interpolation | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Spatial Bezier Interpolation | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Rove Across Time | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| **Masks** | **Android** | **iOS** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | -| Mask Path | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Mask Opacity | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Add | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Subtract | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Intersect | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๏ธโ›” | โ›” | โ›” | -| Lighten | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›” | โ›” | -| Darken | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›” | โ›” | -| Difference | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›” | โ›” | -| Expansion | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | -| Feather | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›” | โ›” | -| **Mattes** | **Android** | **iOS** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | -| Alpha Matte | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | -| Alpha Inverted Matte | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Luma Matte | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ” | โ” | โ” | -| Luma Inverted Matte | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ” | โ” | โ” | -| **Merge Paths** | **Android** | **iOS** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | -| Merge | ๐Ÿ‘ (KitKat+) | โ›” | ๐Ÿ‘ | โ›” | โ›” | โ›” | -| Add | ๐Ÿ‘ (KitKat+) | โ›” | ๐Ÿ‘ | โ›” | โ›” | โ›” | -| Subtract | ๐Ÿ‘ (KitKat+) | โ›” | ๐Ÿ‘ | โ›” | โ›” | โ›” | -| Intersect | ๐Ÿ‘ (KitKat+) | โ›” | ๐Ÿ‘ | โ›” | โ›” | โ›” | -| Exclude Intersection | ๐Ÿ‘ (KitKat+) | โ›” | ๐Ÿ‘ | โ›” | โ›” | โ›” | -| **Layer Effects** | **Android** | **iOS** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | -| Fill | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Stroke | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Tint | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Tritone | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Levels Individual Controls | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| **Text** | **Android** | **iOS** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | -| Glyphs | ๐Ÿ‘ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Fonts | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Transform | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Fill | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Stroke | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Tracking | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Anchor point grouping | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Text Path | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Per-character 3D | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Range selector (Units) | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Range selector (Based on) | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Range selector (Amount) | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Range selector (Shape) | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Range selector (Ease High) | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Range selector (Ease Low) | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Range selector (Randomize order) | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| expression selector | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| **Other** | **Android** | **iOS** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | -| Expressions | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Images | ๐Ÿ‘ | ๐Ÿ‘ | โ” | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Precomps | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Time Stretch | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Time remap | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | -| Markers | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| **Shapes** | **Android** | **iOS (Core Animation)** | **iOS (Main Thread)** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | +|:--|:-:|:-:|:-:|:-:|:-:|:-:|:-:| +| Shape | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Ellipse | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Rectangle | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Rounded Rectangle | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Polystar | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Group | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Repeater | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Trim Path (individually) | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Trim Path (simultaneously) | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| **Fills** | **Android** | **iOS (Core Animation)** | **iOS (Main Thread)** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | +| Color | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Opacity | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Fill Rule | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Radial Gradient | ๐Ÿ‘ | ๐Ÿ‘ | ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Linear Gradient | ๐Ÿ‘ | ๐Ÿ‘ | ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๏ธ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| **Strokes** | **Android** | **iOS (Core Animation)** | **iOS (Main Thread)** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | +| Color | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Opacity | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Width | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Line Cap | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Line Join | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Miter Limit | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Dashes | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Gradient | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| **Transforms** | **Android** | **iOS (Core Animation)** | **iOS (Main Thread)** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | +| Position | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Position (separated X/Y) | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Scale | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Rotation | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Anchor Point | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Opacity | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Parenting | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Auto Orient | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Skew | โ“ | ๐Ÿ‘ | ๐Ÿ‘ | โ“ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| **Interpolation** | **Android** | **iOS (Core Animation)** | **iOS (Main Thread)** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | +| Linear Interpolation | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Bezier Interpolation | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Hold Interpolation | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Spatial Bezier Interpolation | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Rove Across Time | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| **Masks** | **Android** | **iOS (Core Animation)** | **iOS (Main Thread)** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | +| Mask Path | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Mask Opacity | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Add | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Subtract | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Intersect | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | โ›” | โ›” | โ›” | +| Lighten | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›” | โ›” | +| Darken | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›” | โ›” | +| Difference | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›” | โ›” | +| Expansion | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | +| Feather | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›” | โ›” | +| **Mattes** | **Android** | **iOS (Core Animation)** | **iOS (Main Thread)** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | +| Alpha Matte | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Alpha Inverted Matte | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Luma Matte | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ” | โ” | โ” | +| Luma Inverted Matte | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ” | โ” | โ” | +| **Merge Paths** | **Android** | **iOS (Core Animation)** | **iOS (Main Thread)** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | +| Merge | ๐Ÿ‘ (KitKat+) | โ›” | โ›” | ๐Ÿ‘ | โ›” | โ›” | โ›” | +| Add | ๐Ÿ‘ (KitKat+) | โ›” | โ›” | ๐Ÿ‘ | โ›” | โ›” | โ›” | +| Subtract | ๐Ÿ‘ (KitKat+) | โ›” | โ›” | ๐Ÿ‘ | โ›” | โ›” | โ›” | +| Intersect | ๐Ÿ‘ (KitKat+) | โ›” | โ›” | ๐Ÿ‘ | โ›” | โ›” | โ›” | +| Exclude Intersection | ๐Ÿ‘ (KitKat+) | โ›” | โ›” | ๐Ÿ‘ | โ›” | โ›” | โ›” | +| **Layer Effects** | **Android** | **iOS (Core Animation)** | **iOS (Main Thread)** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | +| Fill | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Stroke | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Tint | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Tritone | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Levels Individual Controls | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ” | ๐Ÿ‘ | ๐Ÿ‘ | +| Gaussian blur | ๐Ÿ‘ (4.1+) | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ” | โ” | โ” | +| Drop Shadows | ๐Ÿ‘ (4.1+) | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | โ” | โ” | โ” | +| **Text** | **Android** | **iOS (Core Animation)** | **iOS (Main Thread)** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | +| Glyphs | ๐Ÿ‘ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Fonts | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Transform | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Fill | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Stroke | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Tracking | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Anchor point grouping | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Text Path | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Per-character 3D | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Range selector (Units) | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Range selector (Based on) | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Range selector (Amount) | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Range selector (Shape) | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Range selector (Ease High) | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Range selector (Ease Low) | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Range selector (Randomize order) | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| expression selector | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| **Other** | **Android** | **iOS (Core Animation)** | **iOS (Main Thread)** | **Windows** | **Web (SVG)** | **Web (Canvas)** | **Web (HTML)** | +| Expressions | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Images | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Precomps | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Time Stretch | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Time remap | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | โ›”๏ธ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | +| Markers | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | ๐Ÿ‘ | + +## Drop Shadows and Gaussian Blurs on Android +Drop shadows and gaussian blur effects on Android are applied on each fill or stroke not on the final layer. This has the following side effects: +* If you have many shapes in a layer that has a drop shadow, each shape will get its own shadow and it may appear darker in some areas than others due to overlapping shadows. +* If your blur or shadow extends beyond the bounds of a precomp, the blur or shadow will be clipped. To avoid this, add padding to your precomp. +* Dynamic properties must target the individual fill or strokes that have a blur or shadow even if the effect is applied on the whole layer. The easiest way to do this is to append "**" after the layer name in the KeyPath. This will apply the dynamic property to all applicable children within the layer. + +## iOS: Core Animation rendering engine vs Main Thread rendering engine + +Lottie for iOS includes two rendering engine implementations, which are responsible for actually displaying and rendering Lottie animations: + + - The Core Animation rendering engine (enabled by default in Lottie 4.0+) uses Core Animation `CAAnimation`s to deliver better playback performance than the older Main Thread rendering engine. + - The Main Thread rendering engine (the default before Lottie 4.0) runs code on the main thread once per frame to update and re-render the animation. + +You can learn more about the Core Animation rendering engine in [this post](https://medium.com/airbnb-engineering/announcing-lottie-4-0-for-ios-d4d226862a54) on Airbnb's Tech Blog: **[Announcing Lottie 4.0 for iOS](https://medium.com/airbnb-engineering/announcing-lottie-4-0-for-ios-d4d226862a54)**. + +Most animations are rendered exactly the same by both rendering engines, but as shown above the Core Animation rendering engine and Main Thread rendering engine support slightly different sets of functionality. For example, the Core Animation rendering engine might not support certain complex shape configurations, particularly those involving intersecting or subtracting paths. Due to architectural constraints, these cases may render differently compared to the Main Thread rendering engine. This behavior is expected. +For more details, see [GitHub Issue #2631](https://github.com/airbnb/lottie-ios/issues/2613). + +As of [Lottie 4.0](https://medium.com/airbnb-engineering/announcing-lottie-4-0-for-ios-d4d226862a54), Lottie uses the Core Animation rendering engine by default. If Lottie detects that an animation uses functionality not supported by the Core Animation rendering engine, it will automatically fall back to the Main Thread rendering engine. You can also configure which rendering engine is used by configuring the `LottieConfiguration.renderingEngine`. \ No newline at end of file diff --git a/web.md b/web.md index 8437e2c..d375dc3 100644 --- a/web.md +++ b/web.md @@ -41,11 +41,16 @@ npm install lottie-web ## Bower ```bash -bower install lottie-web +bower install bodymovin ``` --- -# [Video tutorial](https://www.youtube.com/watch?v=5XMUJdjI0L8) +# Video tutorial + +
+ +
+ --- # Usage @@ -82,7 +87,7 @@ animation instances have these main methods: - **anim.goToAndStop(value, isFrame)** first param is a numeric value. second param is a boolean that defines time or frames for first param - **anim.goToAndPlay(value, isFrame)** first param is a numeric value. second param is a boolean that defines time or frames for first param - **anim.setDirection(direction)** -- one param direction (1 is normal direction.) -- **anim.playSegments(segments, forceFlag)** -- first param is a single array or multiple arrays of two values each(fromFrame,toFrame), second param is a boolean for forcing the new segment right awa +- **anim.playSegments(segments, forceFlag)** -- first param is a single array or multiple arrays of two values each(fromFrame,toFrame), second param is a boolean for forcing the new segment right away - **anim.setSubframe(flag)** -- If false, it will respect the original AE fps. If true, it will update as much as possible. (true by default - **anim.destroy()** @@ -161,7 +166,7 @@ Or you can call lottie.searchAnimations() after page load and it will search all ## Lottiefiles.com If you drag an exported json file onto [lottiefiles.com](http://lottiefiles.com), it will preview it directly in the browser. -You can also share the link or scan the ar code with the [Android](https://play.google.com/store/apps/details?id=com.airbnb.lottie&hl=en) or [iOS](https://itunes.apple.com/us/app/lottie-preview/id1231821260?mt=8) app to preview it there as well. +You can also share the link or scan the qr code with the [Android](https://play.google.com/store/apps/details?id=com.airbnb.lottie&hl=en) or [iOS](https://itunes.apple.com/us/app/lottie-preview/id1231821260?mt=8) app to preview it there as well. ## Poster snapshot You can preview or take an svg snapshot of the animation to use as poster. After you render your animation, you can take a snapshot of any frame in the animation and save it to your disk. I recommend to pass the svg through an svg optimizer like https://jakearchibald.github.io/svgomg/ and play around with their settings.
@@ -224,3 +229,9 @@ If an element needs to be rendered larger than the original size, it won't be sm * Some fonts have special combinations of chars that are spaced differently than default. These are not supported yet, they will be spaced as any other char and you might notice some differences. * Some fonts can't be converted to glyphs on AE and will result on an error on the plugin. I've seen this behavior specially with fonts that simulate pixelled fonts. * If you use Typekit fonts, make sure you load them on a single kit, and provide for each font the css Selector displayed on the kit editor. + +## Paths with strokes getting cut off + +If paths with strokes are being cut off to a rectangular viewbox, add a rectangular path larger than the stroked path to the same layer to force the final masked size to include the stroke width. + +![Stroke cutoff issue demo](images/Web-StrokeCutoffMaskingDemo.png) diff --git a/windows.md b/windows.md index c2df64f..6ac21f5 100644 --- a/windows.md +++ b/windows.md @@ -88,7 +88,6 @@ The source code for the samples may be [found here](https://github.com/windows-t Here's more information about supported AfterEffects features and issues you may enocunter: * Comparative list of [supported AfterEffects features](supported-features.md) * Lottie-Windows [version history](https://github.com/windows-toolkit/Lottie-Windows/blob/master/VERSION_HISTORY.md) -* List of [issues and warnings](https://docs.microsoft.com/windows/communitytoolkit/animations/lottie-scenarios/issues) with workarounds where applicable ## Help and Feedback