# Technical Documentation: airbnb/lottie

> ℹ️ **Provenance:** In-Tree Documentation (17 Chapters) · [CodeWiki Reference](https://codewiki.google/github.com/airbnb/lottie) · Recency: Active (< 180 days)

## File: README.md

# 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 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)

---

## File: _sidebar.md

* [**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)
* [**Android - Jetpack Compose**](/android-compose.md)
* [**iOS**](/ios.md)
* [**React Native**](/react-native.md)
* [**Web**](/web.md)
* [**Windows**](/windows.md)
* [**Contribute to Docs**](/docs.md)
* [**Other Platforms**](/other-platforms.md)

---

## File: after-effects.md

# After Effects

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 it's open

### 2 - Install the ZXP installer

[http://aescripts.com/learn/zxp-installer/](http://aescripts.com/learn/zxp-installer/)



### 3 - Download the latest bodymovin extension
[https://github.com/airbnb/lottie-web/tree/master/build/extension](https://github.com/airbnb/lottie-web/blob/master/build/extension/bodymovin.zxp)



### 4 - Open the ZXP installer and drag the bodymovin extension into the window



### 5 - Open After Effects

Under the menu "Window > Extensions" you should see "Bodymovin"



Now you're good to go!

# More Bodymovin info

Check out information about the Bodymovin settings [here](/after-effects/bodymovin-settings.md) 
Also here is a video walkthrough of how to install and use Bodymovin [here](https://www.youtube.com/watch?v=5XMUJdjI0L8)

# Composition Settings

In the Bodymovin panel each composition has a gear next to it which takes to you to the settings. Here is what each of those items means.




**Split:** Attempts to exports animation in multiple json files. If the main comp has more than one layer, the exporter will segment your main comp considering where a layer starts in time.

**Glyphs:** When checked, it will convert all text characters to shapes. If unchecked, you need to provide a font file or a classname in order to render the correct font.

**Hidden:** When checked, it will include all hidden layers. This is usually needed when you have expressions pointing to hidden layers. Keep in mind that all hidden layers will get exported, adding to the final file size

**Guided:** When checked, it will include all guided layers. This is usually needed when you have expressions pointing to guided layers. Keep in mind that all guided layers will get exported, adding to the final file size

**Extra Comps:** You can select additional compositions to be exported as part of the animation. this is only needed if you have expressions pointing to external comps that not included in the main comp or subcomps tree

**Original Assets Name:** If you have rasterized assets like jpgs, it will export them to an images folder with their original source name.

**Standalone:** When checked, it will export the animation and the player all bundled into a single file. Might be useful if you only have one animation in your page. For example for delivering banners.

**Demo:** It will export a demo.html file so you can preview the animation easily.

# Creating Lottie animations

Creating animations for Lottie is a bit different than the usual After Effects workflow. Here are some general tips for creating Lottie animations.

## Keep it Simple

When building for Lottie you always have to keep in mind that these JSON files need to be as compact and small as possible for mobile products. For example use parenting whenever you can. Duplicating the same keyframes on a similar layers adds extra code. Only use path keyframe animations when absolutely have to. Those eat up the most space because its adding data for each vertex on each keyframe. Techniques such as Autotrace, or the wiggler that give you a keyframe every frame, may make your JSON file size very large and may impact performance negatively. There has to be a balance with the way the compositions are setup so that things are as efficient as possible.

## Shape layers for vector artwork / Adobe Illustrator

Convert any Adobe Illustrator, EPS, SVG, or PDF assets to shape layers in After Effects otherwise they will not work in your Lottie animation.



After you've converted to shape layers remove the assets from your composition so they aren't exported with the JSON. Shape layers is where Lottie does best.

## Export at 1x

You can work in After Effects at whatever composition size you want, but be sure to export with a composition size that is 1x the size of your asset.



All pixel values in After Effects will be converted to points on iOS and dps on Android to ensure that they look the same across all screen densities. Google has put together [a collection](https://material.io/devices/) of device metrics with screen size in dps for common devices.

## No expressions or effects

Lottie does not yet support expressions, or any effects from the effects menu.





## Matte and mask size matters

Using alpha mattes can impact performance. If you're using an alpha matte or an alpha inverted matte, the size of the matte will impact performance even more. If you must use Mattes, cover the smallest area you can.

## 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.

## No Blending modes or Luma mattes

Blending modes such as Multiply, Screen or Add, aren't yet supported nor are Luma mattes.

## No layer styles

Lottie does not yet support layer effects like drop shadow, color overlay or stroke.


## Full screen animations

Export an animation wider than the widest screen you intend to support and use the `centerCrop` scale type on Android or the `aspectFill` content mode on iOS.




## Make Nulls visible and have 0% opacity

If you're using a null to control a bunch of layers and usually turn the visibility off, be sure to turn the visibility ON and turn the opacity to 0% otherwise they won't come through in the JSON file

# Sketch/SVG/Illustrator to Lottie workflow

This walkthrough explains how to get artwork from Sketch to Lottie. If you already have an SVG skip to step 3. If you're working in illustrator start at step 4.

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](#Installing%20Bodymovin).


### 1 - Ensure artwork is grouped

To get the asset exported in one piece everything needs to be put into a single group in Sketch



### 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](#debugging)



If you have Googles [Sketch2AE](https://google.github.io/sketch2ae/) tool, you can use that instead. You'll be able to skip steps 3, 4, 5 and 6

### 3 - Open SVG in Illustrator and save as a .AI file




### 4 - Import that .AI file into After Effects

After you open After Effects either drag the illustrator file onto the project window or go to File > Import



### 5 - Create composition, set duration and check Frame-rate

After dragging the Illustrator file down to the little composition icon in the bottom of the project panel you will have a new composition perfectly sized for your file.




Next you can go to the menu and select Composition > Composition settings. I usually work in 30fps or 60fps.

Its important to pick the right frame-rate up front because if you have to change it later things can get weird with pre-existing keyframes. Also you can choose your duration. If you're intending to export a static asset just make the duration a second. If you're going to animate, its up to you. You can always change it again later


### 6 - Convert illustrator file into shape layers

Select the layer in the composition and in the Layer menu select "Create shapes from vector layer" It then creates a new "Shape Layer" based off of your illustrator artwork, that has editable vector properties of the artwork, such as paths, strokes, fills, etc.




So back to that question "Why didn't I just export a PDF or EPS from Sketch??" This is where it counts. When you export a PDF or EPS from Sketch sometimes it adds artboard paths to the shape layer when its converted.



The one on the left is an SVG converted, and the example on the right is an EPS converted. The example on the right you can see the transparency is inverted, because its got some paths that are the size of the artboard. If you have a complicated piece of artwork things can really get strange. You can always go through and cleanup the shape layer by deleting unused paths and artboard paths, its just time consuming and annoying. Thats why SVG is best.


### 6 - Do some animation magic. Or not.

Here you can choose to do some animation magic, or if you're just looking to create a static asset for Lottie you're done.


### 7 - Exporting with Bodymovin

Next if the panel isn't already open go to Window > Extensions > Bodymovin.



Select the composition you want to export by clicking the circle to the left. Next select the destination by selecting the 3 dots on the right. Name your file, and press Render the big green button on the top left


### 8 - Testing your animation

Next step is to test your animation to ensure you're not using any unsupported features, and that everything looks as desired.

There are a few different ways to test, one of the easiest is by using Lottiefiles.com.


### 9 - Upload onto Lottiefiles.com

Open up your browser to Lottiefiles.com and drag your json file directly onto the page



You should see your animation. If it looks correct, thats a great sign, as it means you're using bodymovin supported features.

The next step is to test it on your platform of choice, android or iOS.


### 10 - Download Lottie files preview app

Download the Lottie app from the Google play store or the Lottie Preview app from the App store.




### 11 - Scan the QR code

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.


# Advanced Illustrator to Lottie workflow

Coming soon...

# Troubleshooting

There will be times when your animation looks different in Lottie than it does in After Effects. Here are some things you can try to isolate the problems and find a workaround

## Dig into your shape layers
Sometimes when you bring an asset in from Sketch or Illustrator and convert it to a shape layer there will be some wierd things hidden in your shape layers. Its important to dig in and check each shape layer for errand paths or groups to make your file cleaner.

Heres an example of a file that has extra paths, groups and merge paths. On the left is what was exported from Sketch. You can see there are two weird large artboards that extend way out of the composition bounds and on the right is the cleaned up version which is only the necessary shapes





## Isolate problem layers
Sometimes when you have a really complicated composition with lots of layers you'll need to isolate problem areas. I recommend turning on layers one by one or by groups of a few starting from the bottom of the stack, and just test them until you can see which layer is causing the issues.

Once you see which layer is looking strange you can dig into the shape layer and remove any weird paths or rebuild certain shapes to better work for lottie


## Check for Effects, or Layer styles
Lottie doesnt support effects or layer styles so If a layer has them it will probably be broken in Lottie.


## Check for unsupported features

Coming soon...


## Gradient issues

Coming soon...

## Animation easings are off

Coming soon...

---

## File: android-compose.md

# Getting Started
Add the dependency to your project `build.gradle` file:

<code class="lang-groovy">dependencies {
    ...
    implementation "com.airbnb.android:lottie-compose:$lottieVersion"
    ...
}
</code>
The latest stable version is: 

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: 

# 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<LottieComposition?>
```
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<Float>
```

### 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).

---

## File: android.md

# Getting Started
Add the dependency to your project `build.gradle` file:

<code class="lang-groovy">dependencies {
    ...
    implementation "com.airbnb.android:lottie:$lottieVersion"
    ...
}
</code>
The latest version is: 

# Sample App

You can build the sample app 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.

[](https://play.google.com/store/apps/details?id=com.airbnb.lottie)

---
# 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 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 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:

It is recommended to use `lottie_rawRes` because you can use static references to your animation through `R` instead of just using string names.
#### From res/raw (`lottie_rawRes`) or assets/ (`lottie_fileName`)
```xml
<com.airbnb.lottie.LottieAnimationView
        android:id="@+id/animation_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        app:lottie_rawRes="@raw/hello_world"
        // or
        app:lottie_fileName="hello_world.json"

        // Loop indefinitely
        app:lottie_loop="true"
        // Start playing as soon as the animation is loaded
        app:lottie_autoPlay="true" />
```

### Programmatically

`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.

---
# 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. 

To set it up, somewhere during your application initialization, include:
```kotlin
Lottie.initialize(
    LottieConfig.Builder()
        .setEnableSystraceMarkers(true)
        .setNetworkFetcher(...)
        .setNetworkCacheDir(...)
        .setEnableNetworkCache(false)
)
```

---
# Animation Listeners

You can control the animation or add listeners:
```kotlin
animationView.addAnimatorUpdateListener { animation ->
}
animationView.addAnimatorListener(...)
animationView.addPauseListener {
}

```

In the update listener callback:
`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.

```kotlin
// Custom animation speed or duration.
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`
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:

---
# Dynamic Properties

You can update properties dynamically at runtime. This can be used for a variety of purposes such as:
* Theming (day and night or arbitrary themes).
* Responding to events such as an error or a success.
* 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
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 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
To update a property at runtime, you need 3 things:
1. KeyPath
1. LottieProperty
1. LottieValueCallback

#### 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:
* **Wildcard** `*`
  * Wildcards match any single content name in its position in the keypath.
* **Globstar** `**`
  * Globstars match zero or more layers.

#### 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 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
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.
1. Start value of the current keyframe.
1. End value of the current keyframe.
1. Progress from 0 to 1 in the current keyframe without any time interpolation.
1. Progress in the current keyframe with the keyframe's interpolator applied.
1. Progress in the overall animation from 0 to 1.

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
* LottieValueCallback<T>: 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
```kotlin
animationView.addValueCallback(
  KeyPath("Shape Layer", "Rectangle", "Fill"),
  LottieProperty.COLOR,
  { Color.RED }
)
```

```kotlin
animationView.addValueCallback(
    KeyPath("Shape Layer", "Rectangle", "Fill"),
    LottieProperty.COLOR,
    { if (it.overallProgress < 0.5) Color.GREEN else Color.RED }
)
```

### Animatable Properties

The following value can be modified:

| 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          |

### 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.

---
# Images

Lottie is designed to work with vector shapes. Although Lottie supports rendering images, there are disadvantages to using them:
* The files are an order of magnitude larger than their equivalent vector animation.
* 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.md).

### Setting your images
You can set Lottie images in three ways:
#### 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 use dynamic properties with `LottieProperty.IMAGE`

---
# What is the impact of Lottie on APK size?

Very small:
* ~1600 methods.
* 287kb uncompressed.

---
# Lottie vs Android Vector Drawable (AVD)

There are two ways to render After Effects animations:
1. Export json with Bodymovin and play it with lottie-android.
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](/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.
* Masks are anti-aliased.
* Dynamically change the color of a specific part of an 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.

---
# 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

Lottie supports hardware acceleration but it is disabled out of the box. Read [this article](https://developer.android.com/guide/topics/graphics/hardware-accel.html) to learn more about hardware acceleration. It is disabled by default because it doesn't support anti-aliasing, stroke caps (pre-API 18), and a few other things. In addition, depending on the animation, they may actually be less performant. Read [this article](http://blog.danlew.net/2015/10/20/using-hardware-layers-to-improve-animation-performance/) to understand why.

If you are having performance issues with your animation, make sure to read the [performance](/android/performance.md) docs first. There is more information about how to benchmark and determine if your animation would benefit from hardware acceleration there.

# Merge Paths

Merge paths are only supported on KitKat and above. There is also some performance overhead in using them because [Path.Op](https://developer.android.com/reference/android/graphics/Path.html#op(android.graphics.Path,%20android.graphics.Path.Op) can be slow. To prevent engineers from testing on new devices with merge paths enabled while shipping a broken experience to users on older phones, they are disabled by default. If your `minSdk` is >=19 then you can enable then with `enableMergePathsForKitKatAndAbove()`

# Render Graph
The Lottie sample app has a real time render graph that can be enabled from the menu in the top right. It also has guidelines for 16.66 and 33.333ms per frame which represent the maximum render time to hit 60fps and 30fps respectively.





# Render Times Per Layer
The Lottie sample app also has a bottom sheet with the time it took each layer to render. To access it, click the render graph in the control bar and then tap "View render times per layer".

If there are any layers that are particularly slow, try optimizing their shapes, eliminated masks, mattes, and merge paths where possible.



# Troubleshooting
There may be times in which Lottie doesn't render your animation correctly. After effects has an enormous number of features, not all of which are supported by Lottie. If an animation doesn't look correct, run through the following steps before reporting an issue.

## Check for Warnings
The Lottie for Android will automatically detect and report some errors. It doesn't catch everything but will catch many common cases. You can either call `getWarnings()` from your own code or open the animation in the [Lottie sample app](https://play.google.com/store/apps/details?id=com.airbnb.lottie) and see if warnings show up in the top right. If they do, tapping it will give you more information.



## Check the supported features page.
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.

## Missing merge paths
Merge paths are only available on KitKat and above so you must manually enable them using `enableMergePathsForKitKatAndAbove()`

## Animation Clipping
Make sure you are using the latest version of Lottie.

# Performance Testing



Performance and memory testing was aided by [YourKit](https://www.yourkit.com/java/profiler/) which provides powerful performance and memory profiling tools for Java.

---

## File: community-showcase.md

# Community showcase

Below are some examples of how different individuals and companies are using Lottie in their products. If you're using Lottie and you'd like to be featured in the showcase please email us at [Lottie@airbnb.com](Lottie@airbnb.com) we would love to feature your work so the whole community can be inspired!



## Google Home
Google Home uses Lottie for over 40 different animations in their iOS and Android apps. From intros to connecting loaders, and errors! The animations were designed and animated by Detroit based animation & Illustration studio [Gunner](http://www.gunner.work/).






## Walgreens




## SwiftKey
SwiftKey iOS is using Lottie to help guide their users through the installation of a third party keyboard. With Lottie, they are able to easily control the colours to make their animations high contrast for accessibility, and they're able to scale up to the size of an iPad without losing quality. On a side note, they recently swapped out an old school png sequence which was about 6mb in size, for a lottie json that is just 340kb!






## Elevate
Elevate used a combination of shape layers, alpha mattes and images to craft this silky smooth walkthrough where illustrations seamlessly morph as users swipe to select different training options.



Animation by [Ben Tobias](https://dribbble.com/shots/3474396-Custom-Training-Morph-Animations)
, Illustrations by [Maxime Bourgeois](https://dribbble.com/shots/3473117-Elevate-Custom-Training-Sessions-Animation), [Behance Project page](https://www.behance.net/gallery/51581275/ELEVATE-Custom-Training-Sessions)


## Target
An onboarding flow within the Target apps (iOS and Android) utilized Lottie to bring more personality and joy to this intro experience.




## Uber Eats
Uber eats uses Lottie for their initial loading animation. Simple but effective shapes with trim paths.




## Instacart
Instacart uses Lottie for a handful of educational animations to teach shoppers.



## PenPal
From the onboarding process to animated achievement stamps  users earn, Pen Pals uses Lottie for over 100 different animations inside their app. Check out their  animations for onboarding screens below!



## Popcorn
Onboarding carousel for Popcorn app 🍿.




## RaiseMe
RaiseMe uses Lottie to show students how to earn scholarships from colleges on its iOS app. Illustration and animation by Rachel Schmitz.




## Conio
A Bitcoin/Blockchain startup based in Milan uses  Lottie to better explain some complex part of our product



## Galaxy Watch
Galaxy watch (Tizen OS) uses lottie for watchface and workout application.



## Others

---

## File: docs.md

## 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 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!

---

## File: home.md

# Lottie for&nbsp;[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:



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

[](https://www.lottiefiles.com/)

[](https://lottielab.io/)

[](https://www.airbnb.com/)

[](https://www.emergetools.com/)

[](https://getstream.io/chat/?utm_source=OpenCollective_Lottie&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=Lottie_July2022_Chat_klmh22)

[](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



| [](https://play.google.com/store/apps/details?id=com.airbnb.lottie) | [](https://www.microsoft.com/store/apps/9p7x9k692tmw?ocid=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

---

## File: ios-contributor.md

> 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. 

## Check Before Submitting

Before submitting a PR to Lottie please run through the following checklist.

 - Run 'pod install' in `/Example`
 - Ensure that all targets in `/Example/lottie-swift.xcworkspace` build
 - Add any new files to all of the targets in `/Lottie.xcodeproj`
 - Ensure that all targets build in `/Lottie.xcodeproj`
 
  After making a PR please watch for PR notifications. We will run a series of tests on the PR to ensure that it does not break existing animations.
  
  NOTE: PRs must be approved by the Maintainer of Lottie-ios before they can be merged.

## Project Structure

Lottie is available on iOS and MacOS via CocoaPods, NPM, and Carthage. Because of this, there are some things to consider when adding files to the project. All of the under-the-hood code in Lottie is written to compile in all environments. Specialty wrappers for both `iOS` and `MacOS` are written to give access to Lottie in each environment. These wrappers are designed to be as thin as possible, to avoid code fragmentation.

For example, `UIKit` is only available on iOS, whereas MacOS uses `AppKit`.

### Source Code Directory Structure
All of the source code for Lottie is located in `/lottie-swift/src` in the repo. Here's a quick run down of the directory structure:

 - `src`: The Root directory for all Lottie source files
	 - `Public`: Public facing files.
		 - `Animation`: Files relating to `Animation` and `AnimationView`. *Files in this directory are compiled on both iOS and MacOS.*
		 - `AnimationCache`: Files relating to `AnimationCache`. *Files in this directory are compiled on both iOS and MacOS.*
		 - `DynamicProperties`: All public facing files relating to the Dynamic Properties API. *Files in this directory are compiled on both iOS and MacOS.*
		 - `ImageProvider`: Holds the `ImageProvider` protocol. *Files in this directory are compiled on both iOS and MacOS.*
		 - `MacOS`: Files that are **only** compiled for MacOS. *Files in this directory are compiled on MacOS.*
		 - `Primitives`: Primitive data structures. *Files in this directory are compiled on both iOS and MacOS.*
		 - `iOS`: Files that are **only** compiled for iOS. *Files in this directory are compiled on iOS.*
	 - `Private`: Private `internal` files. *Files in this directory are compiled on both iOS and MacOS.*

### Adding a file to the project.

Because Lottie supports multiple distributions/platforms, adding a file to the project takes a couple of steps.

1. Add the new source file into the appropriate directory. Think about the new source file's purpose and what platform it will be available on.
2. After adding the new file, test that it can install and compile with CocoaPods. Navigate to `/Example` in terminal and run `pod install`. Afterwards open [lottie-swift.xcworkspace](/Example/lottie-swift.xcworkspace "lottie-swift.xcworkspace") and build all of the target platforms to ensure that nothing is broken.
3. Add the files to the Carthage build. Open [Lottie.xcodeproj](/Lottie.xcodeproj "Lottie.xcodeproj"). Add the new file to the project. **Uncheck Copy File when adding new files to this project**.  Check the files Target Membership in the right panel and make sure it is added to the appropriate targets. There are two targets, on dynamic and one static, for each platform (iOS, tvOS, macOS). After adding the targets run through and build all of the targets.
4. Celebrate! You've done it!

## After Effects Primer
Before digging into Lottie, let's take a look at how After Effects builds animation. Lottie structures a lot of its render system in a similar way to After Effects.

### Layers
An After Effects `Composition` is a top level object that holds an animation timeline and several `Layers`. These `Layers` are different from Layers in iOS, which can describe any rendered frame. A `Layer` is more of a top level container, that holds its contents and can transform it. There are a couple of types of `Layer`, each with it's own unique contents. They are:

- `Image layer`: Contains an image and a `Transform`
- `Null Layer`: Contains only a`Transform`
- `Shape Layer`: Contains a group of `Shape Objects`
- `Solid Layer`: Contains a colored rectangle
- `Text Layer`: Contains rendered `Text`
- `Precomp Layer`: Contains another composition, with its own group of `Layers`

A `Composition` has a timeline, and almost every property in After Effects can be keyframed to change over time. As the current time on a timeline is changed every property with keyframe data is interpolated and updated, creating animation.

Each `Layer` has a `Transform` which transforms the layer's contents in space. A `Transform` can position, rotate, scale, skew, and change the opacity of a layer's contents. Each of these properties can be animated.

`Layers` can be parented to another layer. A layer is affect not only by it's own `Transform` but also by its `Parent`. `Layers` also each hold a list of `Masks` that affect their appearance. `Masks` are bezier shape paths that are used to cut out portions of the layer.

### Shape Layers
The `Shape Layer` is the bread and butter of Lottie. A `Shape Layer` can hold several `Shape Objects`. You can think of a `Shape Object` as a single render instruction. At render time, each `Shape Object` is read in order and together create a rendering on screen.  Each `Shape Object` has its own list of animatable properties that defines it's output. There are three basic classes of `Shape Objects`, each with a handful of subtypes.

- **Path Generators**: Create bezier path data to be rendered and adds it to the current state. Some path generators are `Ellipse` `Rect` `Polystar`

- **Modifiers**: Alters bezier path data from the current state. Some Modifiers are `Trim Path` `Merge Path` `Transform Path`

- **Renderers**: Renders the current bezier path data on screen. Some Renderers are `Fill Path` `Stroke path`

A set of `Shape Objects` are held in a `Group`, which can be nested inside other `Groups`. A `Shape Layer` can hold an unlimited number of `Shape Objects`

## Lottie's Node System

The simplest way to recreate After Effects' render system would be to nest all of the render instruction into a `CALayer` and have the layer draw it's contents. This wouldn't be very performant however, as a layer would have to redraw it's entire contents if there was even the slightest of updates. In fact this is how After Effects works, each frame is entirely redrawn when anything changes. After Affects can afford to work this way, as it is not a realtime renderer.

Lottie works in a different way. Every renderable instruction is nested in it's own `CALayer`.  Every frame a `Node Tree` determines which properties have updates, and only updates the affected layers. If a renderer doesn't have any updates, it is not redrawn. This greatly improves performance and allows for realtime rendering of animations.

The Node System is designed to efficiently updates render contents. Additionally the Node System was designed to be as clean and composable as possible.

### Animator Node



The `Animator Node` is a protocol that defines an object with a group of animatable properties. Every `Shape Object` is an `Animator Node`.  A `Shape Layer` holds a linked-list tree of `Animator Nodes` that it updates each frame. `Animator Nodes` are not directly responsible for rendering on screen, they are only responsible for checking for updates and building the data used for rendering. 

An `Animator Node` will build it's output and put it into an `Output Node`. This node is later referenced by a `ShapeRenderLayer` which is responsible for rendering the output.

Every frame a `Shape Layer` asks it's root `Animator Node` to update. The `Animator Node` check's if it has any updates, updates its properties if necessary, and then recursively updates it's parent `Animator Node`. If an `Animator Node` has any updates it will rebuild its outputs, and mark them as updates. At render time anything marked with an update is rendered.

### Node Property Map



An `Animator Node` holds reference to a `Node Property Map`. The `Node Property Map` holds a list of `Node Property` objects, and is responsible for updating them each frame. Additionally the `Node Property Map` can map to its `Node Property` objects by a key.

### Node Property



A `Node Property` holds both a `Value Provider` and a `Value Container`. During an update the `Node Property` will ask the `Value Provider` if it has an update. If it does the `Node Property` will get the new value from the `Value Provider` and store it in the `Value Container`. The property and the container will be marked as having an update.

Additionally, the `Value Provider` of a `Node Property` can be dynamically changed, allowing animations to be altered at runtime.

### Value Provider



The `Value Provider` protocol defines a handful of methods for retrieving a typed value over time. Each frame a `Value Provider` is asked if it has an update, and then is asked for it's value.

A `Value Provider` can be a list of keyframes that interpolates over time, a single unchanging value, or a dynamic object that is changed from outside of Lottie.

### Value Container



The `Value Container` holds reference to a single output value. The node is marked if it has been updated, and can be references from many sources. Ultimately an `Animator Node` will read the value from the container and build its output.

### Output Node



The `Output Node` holds reference to the final output of an `Animator Node`. `Output Node` objects are linked together into their own tree that is held by the render layers. After the `Animator Node` tree is updated the `Output Node` tree is used by the render layers to redraw it's contents. Every `Output Node` has a parent node and an `outputPath`. The `outputPath` is the sum of its parent's output and its out data.

An `Output Node` generally falls into one of three types, which match the three classes of `Shape Objects` in After Effects.

- `Path Output Node`: Holds a generated bezier path
- `Path Modifier`: Modifies its input path and set the output.
- `Renderer`: Holds instructions for rendering the current path data.


## The Update Cycle



A `ShapeCompositionLayer` is a top level `CALayer` that holds a `Node Tree` and a `Render Container`. Each frame of animation the `ShapeCompositionLayer` is given a frame. Render updates happen in two passes: 
 1. The Node Tree is updated
 2. The child Render Layers are updated. 




*The Animator Node update cycle*

This is the update cycle for a single `Animator Node`. When the `ShapeCompositionLayer` receives a frame it tells its root `Animator Node` to update with the frame. The `Animator Node` calls recursively upstream to start updates at the top of the tree. An `Animator Node` asks its `Node Property Map` if there are updates. The property map holds a list of `Node Property` objects. Each one is asked if it has an update. That call is passed through to the `Value Provider`, and also the `Value Container` if either return `true` then the property is marked for update. Next the `Node Property Map` loops through its properties and asks them to update if necessary. The `Node Property` asks its `Value Provider` for its value and then stores it in the `Value Container`.

After all of the `Node Properties` have updates the `Animator Node` passes its update state down stream. Once the entire tree has updated its properties it starts to rebuild its outputs. Outputs are rebuilt from the bottom of the tree up to the top. If an `Animator Node` was marked as updated during its update pass it rebuilds its output. `updateOutputs` is called. Here an `Animator Node` executes its custom code for building its outputs. It reads the values of its properties `Value Container` and builds the output that is stored in its `Output Node`. Afterwards it calls up the tree to continue the update process.

Once all of the nodes have marked themselves, and updated their outputs, the `ShapeCompositionLayer` moves on to the render side of the update.



*The Render Node update cycle*

The `Shape Composition Layer` tells it's `Shape Container Layer` to mark it's updates. The `Shape Container Layer` loops through its child `Shape Render Layers`.

Each `Shape Render Layer` holds reference to a `Renderer`. A `Renderer` is a type of `Output Node` that has render instructions in addition to an `outputPath`. The `Shape Render Layer` asks its renderer if there are updates for the frame. If the renderer returns `true` the `Shape Render Layer` calls `setNeedsDisplay` on itself which loops into `CALayer` update system. 

When `display` is called on the `Shape Render Layer` it asks its render for render instructions and the layer is redrawn.

🎉🎉🎉

## Current Animator Nodes

### Modifier Nodes
- `TrimPathNode`: Trims a collection of paths by a percentage of their length
### Render Nodes
- `FillNode`: Fills all input paths with a solid color
- `StrokeNode`: Strokes all input paths with a solid color
- `GradientFillNode`: Fills all input paths with a gradient color
- `GradientStrokeNode`: Strokes all input paths with a gradient color
### Path Nodes
- `EllipseNode`: Generates an Ellipse Path
- `PolygonNode`: Generates a Polygon Path with N sides
- `RectNode`: Generates an Rectangular Path
- `ShapeNode`: Generates an Path with bezier path data
- `StarNode`: Generates an Star Path
### Container Nodes
- `GroupNode`: Holds and renders a group of node objects
### Specialty Nodes
- `TransformNode`: Supplies top level Layers with transforms
- `TextAnimatorNode`: Supplies a Text Layer with its text contents

## Example Animator Node

For example, let us implement one of the simplest `Animator Nodes`, the `Fill Node`. 

The `Fill Node` is a node that renders a filled shape with a solid color.  It only has a few properties: `color` `opacity` and `fillRule`. 

An `Animator Node` has a `Node Property Map` that maps its properties. Lets create a property map fot the `Fill Node`:

```swift
class FillNodeProperties: NodePropertyMap, KeypathSearchable {

	var keypathName: String
	
	init(fill: Fill) {
		/// The node is initialized with a `Fill` model.
		self.keypathName = fill.name
		/// Create a Node Property with a group of Color Keyframes
		self.color = NodeProperty(provider: KeyframeInterpolator(keyframes: fill.color.keyframes))
		/// Create a Node Property with a group of Float Keyframes
		self.opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: fill.opacity.keyframes))
		/// Set the fill rule.
		self.type = fill.fillRule
		/// Make a key map of the properties, enabling dynamic property setting.
		self.keypathProperties = [
			"Opacity" : opacity,
			"Color" : color
		]
		/// Set the properties.
		self.properties = Array(keypathProperties.values)
	}

	let opacity: NodeProperty<Vector1D>
	let color: NodeProperty<Color>

	let type: FillRule

	let keypathProperties: [String : AnyNodeProperty]
	let properties: [AnyNodeProperty]

}
```

Now we have created a robust property map for our Fill Node.
An `Animator Node` also needs an `OutputNode`. The Fill Node has a Renderer output type, that renders path objects with a fill. Let's create the Renderer `OutputNode`
```Swift
/// An OutputNode that holds render instructions for Fill
class FillRenderer: PassThroughOutputNode, Renderable {

	/// A Render Node can either update a CAShapeLayer, or render directly into a context.
	/// This node can accomplish its rendering with a CAShapeLayer
	let shouldRenderInContext: Bool = false
	
	/// Output Node Properties. Notice how setting these properties sets hasUpdate to `true`
	
	/// The fill color.
	var color: CGColor? {
		didSet {
			hasUpdate = true
		}
	}
	
	/// The fill opacity.
	var opacity: CGFloat = 0 {
		didSet {
			hasUpdate = true
		}
	}

	//// The fill rule.
	var fillRule: FillRule = .none {
		didSet {
			hasUpdate = true
		}
	}

	/// The function that is called when render updates happen.
	func updateShapeLayer(layer: CAShapeLayer) {
		layer.fillColor = color
		layer.opacity = Float(opacity)
		layer.fillRule = fillRule.caFillRule
		/// Clear the update flag. The job is done.
		hasUpdate = false
	}
	
	/// Optional, the context renderer. 
	/// setting shouldRenderInContext to `true` would cause this method to be called.
	func render(_ inContext: CGContext) {
		guard inContext.path != nil && inContext.path!.isEmpty == false else {
			return
		}
		guard let color = color else { return }
		hasUpdate = false
		inContext.setAlpha(opacity * 0.01)
		inContext.setFillColor(color)
		inContext.fillPath(using: fillRule.cgFillRule)
	}
}
```

Now we have a `Renderer` `OutputNode` capable of rendering a fill. We are now ready to create our `FillNode`

```swift

/// An `Animator Node` capable of fill rendering.
class FillNode: AnimatorNode, RenderNode {
	
	/// The fill renderer.
	let fillRender: FillRenderer
	
	/// Protocol RenderNode requires a `Renderable`
	var renderer: NodeOutput & Renderable {
		return  fillRender
	}

	/// The Fill properties.
	let fillProperties: FillNodeProperties

	/// Initialized with a `Fill` model.
	init(parentNode: AnimatorNode?, fill: Fill) {
		/// Create the Renderer
		self.fillRender = FillRenderer(parent: parentNode?.outputNode)
		/// Create the Properties
		self.fillProperties = FillNodeProperties(fill: fill)
		/// Set the upstream parent node.
		self.parentNode = parentNode
	}

	// MARK: Animator Node Protocol
	
	var propertyMap: NodePropertyMap & KeypathSearchable {
		return  fillProperties
	}

	let parentNode: AnimatorNode?
	var hasLocalUpdates: Bool = false
	var hasUpstreamUpdates: Bool = false
	var lastUpdateFrame: CGFloat? = nil
	
	/// Changes to this node do not affect downstream nodes.
	func localUpdatesPermeateDownstream() -> Bool {
		return  false
	}
	
	/// Set up the renderer.
	func rebuildOutputs(frame: CGFloat) {
		fillRender.color = fillProperties.color.value.cgColorValue
		fillRender.opacity = fillProperties.opacity.value.cgFloatValue * 0.01
		fillRender.fillRule = fillProperties.type
	}

}
```

And that's that!
Now, when connected to a Node Tree, the fill node will render its contents only when its contents, or its upstream nodes, have updated.

---

## File: ios.md

# Supported Platforms

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'
```

And then run:
```ruby
pod install
```
After installing the cocoapod into your project import Lottie with
```swift
import Lottie
```

## Carthage
Add Lottie to your Cartfile:
```
github "airbnb/lottie-ios" "master"
```

And then run:
```
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.

# 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 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 = LottieAnimationView(name: "StarAnimation")
```
Additionally you can choose to load an `LottieAnimationView` without any animation, and set the animation later:
```swift
let starAnimationView = LottieAnimationView()
/// Some time later
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)

After loading an animation it can be played with:
```swift
starAnimationView.play { (finished) in
  /// LottieAnimation finished
}
```
Read more about playing animations [Here](#playing-animations)

## 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")
  }
}
```

# 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 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).
#
### Loading from a Bundle
```swift
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. 

Parameters:
: **name**: The name of the json file without the json extension. EG "StarAnimation"
: **bundle**: The bundle in which the animation is located. Defaults to `Bundle.main`
: **subdirectory**: A subdirectory in the bundle in which the animation is located. Optional.
: **animationCache**: A cache for holding loaded animations. Optional.

Example:
```swift
/// Load from the main bundle.
let animation = LottieAnimation.named("StarAnimation")
/// Load from a specific bundle/
let animation = LottieAnimation.named("StarAnimation", bundle: myBundle)
/// Load from a subdirectory in a bundle.
let animation = LottieAnimation.named("StarAnimation", subdirectory: "Animations")
/// Load with an animation cache.
let animation = LottieAnimation.named("StarAnimation", animationCache: LRUAnimationCache.sharedCache)
```

### Loading from a Filepath
```swift
LottieAnimation.filepath(_ filepath: String, animationCache: AnimationCacheProvider?) -> LottieAnimation?
```
Loads an animation model from an absolute filepath. Returns `nil` if an animation is not found. 

Parameters:
: **filepath**: The absolute filepath of the animation to load. EG "/User/Me/starAnimation.json"
: **animationCache**: A cache for holding loaded animations. Optional.

Example:
```swift
let animation = LottieAnimation(filepathURL.path, animationCache: LRUAnimationCache.sharedCache)
```

# 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 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
`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
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 `LottieAnimationView`

### Basic Playing
```swift
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.

Parameters:
: **completion**: A completion block that is called when the animation completes. The block will be passed `true` if the animation completes and `false` if the animation was interrupted. Optional.

Example:
```swift
starAnimationView.play { finished in
  /// LottieAnimation stopped
}

// SwiftUI LottieView API
LottieView(animation: myAnimation)
  .playing()
  .animationDidFinish { finished in
    /// LottieAnimation did finish
  }
```

### Play with Progress Time
```swift
LottieAnimationView.play(fromProgress: AnimationProgressTime?, toProgress: AnimationProgressTime, loopMode: LottieLoopMode?, completion: LottieCompletionBlock?)
```
Plays the animation from a `Progress Time` to a `Progress Time` with options.

Parameters:
: **fromProgress**: The start progress of the animation. If `nil` the animation will start at the current progress. (Optional)
: **toProgress**: The end progress of the animation.
: **loopMode**: The loop behavior of the animation. If `nil` the view's `loopMode` property will be used.  (Optional)
: **completion**: An optional completion closure to be called when the animation stops.  (Optional)

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
```swift
LottieAnimationView.play(fromFrame: AnimationProgressTime?, toFrame: AnimationFrameTime, loopMode: LottieLoopMode?, completion: LottieCompletionBlock?)
```
Plays the animation from a `Frame Time` to a `Frame Time` with options.

Parameters:
: **fromFrame**: The start frame of the animation. If `nil` the animation will start at the current frame. (Optional)
: **toFrame**: The end frame of the animation.
: **loopMode**: The loop behavior of the animation. If `nil` the view's `loopMode` property will be used.  (Optional)
: **completion**: An optional completion closure to be called when the animation stops.  (Optional)

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
```swift
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 LottieAnimation data and assigned a name.
Read more on Markers [here](#using-markers)
==NOTE==: If markers are not found the play command will exit. 

Parameters:
: **fromMarker**: The start marker for the animation playback. If `nil` the animation will start at the current progress. (Optional)
: **toMarker**: The end marker for the animation playback.
: **loopMode**: The loop behavior of the animation. If `nil` the view's `loopMode` property will be used.  (Optional)
: **completion**: An optional completion closure to be called when the animation stops.  (Optional)

Example:
```swift
/// 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
```swift
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
```swift
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)
```

## LottieAnimation Settings
`LottieAnimationView` has a variety of settings for controlling playback, and visual state.

### Content Mode
```swift
/// iOS
var LottieAnimationView.contentMode: UIViewContentMode { get set }
/// MacOS
var LottieAnimationView.contentMode: LottieContentMode { get set }
```
Describes how the LottieAnimationView should resize and scale its contents.

Options:
: **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 LottieAnimationView.backgroundBehavior: LottieBackgroundBehavior { get set }
```
Describes the behavior of an LottieAnimationView when the app is moved to the background. (iOS only)

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. 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 LottieAnimationView.loopMode: LottieLoopMode { get set }
```
Sets the loop behavior for `play` calls. Defaults to `playOnce`
Options:
: **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 LottieAnimationView.isAnimationPlaying: Bool { get set }
```
Returns `true` if the animation is currently playing, `false` if it is not.

### Should Rasterize When Idle
```swift
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. 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 LottieAnimation Frame Rate
```swift
var LottieAnimationView.respectAnimationFrameRate: Bool { get set }
```
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`

### LottieAnimation Speed
```swift
var LottieAnimationView.animationSpeed: CGFloat { get set }
```
Sets the speed of the animation playback. Higher speed equals faster time.
Defaults to `1`
#
### Current Progress
```swift
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
```swift
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
```swift
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 LottieAnimationView.realtimeAnimationFrame: AnimationFrameTime { get }
```
Returns the realtime Frame Time of an LottieAnimationView while an animation is in flight.
ress
```swift
var LottieAnimationView.realtimeAnimationProgress: AnimationProgressTime { get }
```
Returns the realtime Progress Time of an LottieAnimationView while an animation is in flight.


## 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 `LottieAnimation` and `LottieAnimationView` have methods for reading Marker Times.

### Reading Marker Time
```swift
/// 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 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
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.

Parameters
: **valueProvider**: The new value provider for the property.
: **keypath**: The keypath used to search for properties.

Example:
```swift
/// A keypath that finds the color value for all `Fill 1` nodes.
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 LottieAnimation Properties
```swift
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.
: **atFrame**: The Frame Time of the value to query. If nil then the current frame is used.

Example:
```swift
/// A keypath that finds the Position of `Group 1` in `Layer 1`
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
```swift
// 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.

# Rendering Engines

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 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)**.

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).

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. 

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`.


# Image Provider
Image provider is a protocol that is used to supply images to `LottieAnimationView`.

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
```swift
public class BundleImageProvider: AnimationImageProvider
```
An `AnimationImageProvider` that provides images by name from a specific bundle. The `BundleImageProvider` is initialized with a bundle and an optional searchPath.

```swift
/// Create a bundle that loads images from the Main bundle in the subdirectory "AnimationImages"
let imageProvider = BundleImageProvider(bundle: Bundle.main, searchPath: "AnimationImages")
/// Set the provider on an animation.
animationView.imageProvider = imageProvider
```

## FilepathImageProvider
```swift
public class FilepathImageProvider: AnimationImageProvider
```
An `AnimationImageProvider` that provides images by name from a specific local filepath.

```swift
/// Create a bundle that loads images from a local URL filepath.
let imageProvider = AnimationImageProvider(filepath: url)
/// Set the provider on an animation.
animationView.imageProvider = imageProvider
```

# LottieAnimation 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.

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.


# 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

ValueProviders work with a few Primitive data types. 

 - **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
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(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")
/// Set the provider on the animationView.
animationView.setValueProvider(redValueProvider, keypath: fillKeypath)

/// Later...
/// Changing the value provider will update the animation.
redValueProvider.color = LottieColor(r: 0, g: 0.2, b: 1, a: 1)
```
# 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 `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. 

Keypath Examples:
```
/// Represents a specific color node on a specific stroke.
@"Layer.Shape Group.Stroke 1.Color"
```
```
/// Represents the color node for every Stroke named "Stroke 1" in the animation.
@"**.Stroke 1.Color"
```

Code Example:
```swift
/// A keypath that finds the color value for all `Fill 1` nodes.  
let fillKeypath =  AnimationKeypath(keypath:  "**.Fill 1.Color")
```

# 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.

The `AnimatedControl` will show and hide layers depending on the current `UIControl.State` of the control.

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.

# Animated Switch

Also available as `LottieSwitch`, a SwiftUI `View` implementation.



An interactive switch with an 'On' and 'Off' state. When the user taps on the switch the state is toggled and the appropriate animation is played.

Both the 'On' and 'Off' have an animation play range associated with their state.

To change the play range for each state use:
```swift
/// Sets the play range for the given state. When the switch is toggled, the animation range is played.
public func setProgressForState(fromProgress: AnimationProgressTime,
    toProgress: AnimationProgressTime,
    forState onState: Bool)
```

# Animated Button

Also available as `LottieButton`, a SwiftUI `View` implementation.



An interactive button that plays an animation when pressed.
The `AnimatedButton` can play a variety of time ranges for different `UIControl.Event`.  Play ranges are set using either:
```swift
/// Set a play range with Progress Time.
public func setPlayRange(fromProgress: AnimationProgressTime, 
    toProgress: AnimationProgressTime, 
    event: UIControl.Event)
/// Set a play range with Marker Keys.
public func setPlayRange(fromMarker fromName: String, 
    toMarker toName: String, 
    event: UIControl.Event)
```
Once set the  animation will automatically play when the event is triggered.

Example:
```swift
/// Create a button.
let twitterButton = AnimatedButton()
twitterButton.translatesAutoresizingMaskIntoConstraints = false
/// Set an animation on the button.
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
twitterButton.setPlayRange(fromMarker: "touchDownStart", toMarker: "touchDownEnd", event: .touchDown)
twitterButton.setPlayRange(fromMarker: "touchDownEnd", toMarker: "touchUpCancel", event: .touchUpOutside)
twitterButton.setPlayRange(fromMarker: "touchDownEnd", toMarker: "touchUpEnd", event: .touchUpInside)
view.addSubview(twitterButton)
```

# 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.


It's easy to create the four switches and play them:

```swift
let animationView = LottieAnimationView(name: "toggle");
self.view.addSubview(animationView)
animationView.play()

let animationView2 = LottieAnimationView(name: "toggle");
self.view.addSubview(animationView2)
animationView2.play()

let animationView3 = LottieAnimationView(name: "toggle");
self.view.addSubview(animationView3)
animationView3.play()

let animationView4 = LottieAnimationView(name: "toggle");
self.view.addSubview(animationView4)
animationView4.play()

```
## Now lets change their colors


```swift

/// A Color Value provider that returns a reddish color.
let redValueProvider = ColorValueProvider(Color(r: 1, g: 0.2, b: 0.3, a: 1))
/// A Color Value provider that returns a reddish color.
let orangeValueProvider = ColorValueProvider(Color(r: 1, g: 1, b: 0, a: 1))
/// A Color Value provider that returns a reddish color.
let greenValueProvider = ColorValueProvider(Color(r: 0.2, g: 1, b: 0.3, a: 1))



let keypath = AnimationKeypath(keypath: "BG-On.Group 1.Fill 1.Color")
animationView2.setValueProvider(greenValueProvider, keypath: keypath)

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.
LottieAnimationView provides `func logHierarchyKeypaths()` which will recursively log all settable keypaths for the animation.


"BG-On.Group 1.Fill 1.Color"

## Now lets change a couple of properties


Lottie allows you to change **any** property that is animatable in After Effects. 

# 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.

# 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 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.

If you have a question or feature request, please start a discussion here:
https://github.com/airbnb/lottie-ios/discussions

---

## File: other-platforms.md

# Third Party Platforms
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)
* [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)
* [Vue](https://github.com/chenqingspring/vue-lottie)
* [Angular](https://github.com/chenqingspring/ng-lottie)
* [Polymer](https://github.com/reemardelarosa/polymate)

# 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)

---

## File: react-native.md

# Lottie React Native

[](https://www.npmjs.com/package/lottie-react-native) [](https://www.npmjs.com/package/lottie-react-native)

Lottie component for React Native ([Repo](https://github.com/lottie-react-native/lottie-react-native))

# Installing

## 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):

```
yarn add lottie-react-native
```

Go to your ios folder and run:

```
pod install
```

## Web

- Install `lottie-react-native` (latest):

```
yarn add lottie-react-native
```

- Add dependencies for web players:

```
yarn add @dotlottie/react-player @lottiefiles/react-lottie-player
```

## Windows (React Native >= 0.63)


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
<PropertyGroup Label="LottieReactNativeProps">
    <LottieReactNativeDir>$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\lottie-react-native\package.json'))\node_modules\lottie-react-native</LottieReactNativeDir>
</PropertyGroup>
<ImportGroup Label="LottieReactNativeTargets">
    <Import Project="$(LottieReactNativeDir)\src\windows\cppwinrt\PropertySheets\LottieGen.Auto.targets" />
</ImportGroup>
```

Add the LottieReactNative.vcxproj file to your Visual Studio solution to ensure it takes part in the build.

For C# apps, you'll need to install the following packages through NuGet:

- 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 `<EnableLottieDynamicSource>false</EnableLottieDynamicSource>` 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 `<WinUIVersion>` property.

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()));
```

```cpp
// C++
#include <winrt/LottieReactNative.h>
#include <winrt/AnimatedVisuals.h>

...

PackageProviders().Append(winrt::LottieReactNative::ReactPackageProvider(winrt::AnimatedVisuals::LottieCodegenSourceProvider()));
```

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:

```xml
<!-- .vcxproj or .csproj -->
<ItemGroup>
    <LottieAnimation Include="Assets/Animations/MyAnimation.json" Name="MyAnimation" />
</ItemGroup>
```

```js
// js
<LottieView source={"MyAnimation"} style={{width: "100%", height: "100%"}} />
```

Codegen is available to both C# and C++ applications. Dynamic loading of JSON strings at runtime is currently only supported in C# applications.



# Usage

Lottie can be used in a declarative way:

```jsx
import React from "react";
import LottieView from "lottie-react-native";

export default function Animation() {
  return (
    <LottieView
      source={require("../path/to/animation.json")}
      style={{width: "100%", height: "100%"}}
      autoPlay
      loop
    />
  );
}
```

Additionally, there is an imperative API which is sometimes simpler.

```tsx
import React, { useEffect, useRef } from "react";
import LottieView from "lottie-react-native";

export default function AnimationWithImperativeApi() {
  const animationRef = useRef<LottieView>(null);

  useEffect(() => {
    animationRef.current?.play();

    // Or set a specific startFrame and endFrame with:
    animationRef.current?.play(30, 120);
  }, []);

  return (
    <LottieView
      ref={animationRef}
      source={require("../path/to/animation.json")}
      style={{width: "100%", height: "100%"}}
    />
  );
}
```

Lottie's animation view can be controlled by either React Native Animated or Reanimated API.

```tsx
import React, { useEffect, useRef, Animated } from "react";
import { Animated, Easing } from "react-native";
import LottieView from "lottie-react-native";

const AnimatedLottieView = Animated.createAnimatedComponent(LottieView);

export default function ControllingAnimationProgress() {
  const animationProgress = useRef(new Animated.Value(0));

  useEffect(() => {
    Animated.timing(animationProgress.current, {
      toValue: 1,
      duration: 5000,
      easing: Easing.linear,
      useNativeDriver: false,
    }).start();
  }, []);

  return (
    <AnimatedLottieView
      source={require("../path/to/animation.json")}
      progress={animationProgress.current}
      style={{width: "100%", height: "100%"}}
    />
  );
}
```

Changing color of layers:

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 (
    <LottieView
      source={require("../path/to/animation.json")}
      colorFilters={[
        {
          keypath: "button",
          color: "#F00000",
        },
        {
          keypath: "Sending Loader",
          color: "#F00000",
        },
      ]}
      style={{width: "100%", height: "100%"}}
      autoPlay
      loop
    />
  );
}
```

# If you want to use `.lottie` files

You need to modify your `metro.config.js` file accordingly by adding `lottie` extension to the `assetExts` array:

```js
const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config");

const defaultConfig = getDefaultConfig(__dirname);

/**
 * 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

Create a file in the following path `__mocks__/lottieMock.js` and add the following code:

```js
module.exports = "lottie-test-file-stub";
```

Then add the following to your `jest.config.js` file:

```js
module.exports = {
  ...
  moduleNameMapper: {
    ...,
    '\\.(lottie)$': '<rootDir>/jest/__mocks__/lottieMock.js',
  },
  ...
}
```

# API

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:

| 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).                                                                                                                                                                                    | `[]`                                                                                                                            |

[More...](https://github.com/airbnb/lottie-react-native/blob/master/docs/api.md)

# Troubleshooting

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.

For further troubleshooting, please refer to the [troubleshooting guide](https://github.com/lottie-react-native/lottie-react-native#troubleshooting).

---

## File: sponsorship.md

# 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.

---

## File: supported-features.md

# Supported Features

| **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`.

---

## File: web.md

# Getting Started
Bodymovin can render Lottie JSON files on the web.

First, get the bodymovin player javascript library. It is statically hosted at [https://cdnjs.com/libraries/bodymovin](https://cdnjs.com/libraries/bodymovin) or you can get the javascript directly by clicking `Get Player` in the bodymovin plugin.

```html
<script src="js/bodymovin.js" type="text/javascript"></script>
<!-- OR -->
<script src="https://cdnjs.com/libraries/bodymovin" type="text/javascript"></script>
```

Bodymovin is also available on npm and bower.

Then playing the animation is as simple as:
```javascript
var animation = bodymovin.loadAnimation({
  container: document.getElementById('lottie'), // Required
  path: 'data.json', // Required
  renderer: 'svg/canvas/html', // Required
  loop: true, // Optional
  autoplay: true, // Optional
  name: "Hello World", // Name for future reference. Optional.
})
```

# HTML player installation
## Static URL
Or you can use the script file from here:
https://cdnjs.com/libraries/lottie-web

## From Extension
Or get it directly from the AE plugin clicking on Get Player

## lottie light
The extension includes `lottie_light.js` which will play animations exported as svgs.

## NPM
```bash
npm install lottie-web
```

## Bower
```bash
bower install bodymovin
```

---
#  Video tutorial 





---

# Usage
Call lottie.loadAnimation() to start an animation.
It takes an object as a unique param with:
- animationData: an Object with the exported animation data.
- path: the relative path to the animation object. (animationData and path are mutually exclusive)
- loop: true / false / number
- autoplay: true / false it will start playing as soon as it is ready
- name: animation name for future reference
- renderer: 'svg' / 'canvas' / 'html' to set the renderer
- container: the dom element on which to render the animation


It returns the animation instance you can control with play, pause, setSpeed, etc.

```js
lottie.loadAnimation({
  container: element, // the dom element that will contain the animation
  renderer: 'svg',
  loop: true,
  autoplay: true,
  path: 'data.json' // the path to the animation json
});
```

## Usage
animation instances have these main methods:
- **anim.play()**
- **anim.stop()**
- **anim.pause()**
- **anim.setLocationHref(locationHref)** -- one param usually pass as `location.href`. Its useful when you experience mask issue in safari where your url does not have `#` symbol.
- **anim.setSpeed(speed)** -- one param speed (1 is normal speed)
- **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 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()**

lottie has 8 main methods:
- **lottie.play()** -- with 1 optional parameter **name** to target a specific animation 
- **lottie.stop()** -- with 1 optional parameter **name** to target a specific animation 
- **lottie.setSpeed()** -- first param speed (1 is normal speed) -- with 1 optional parameter **name** to target a specific animation 
- **lottie.setDirection()** -- first param direction (1 is normal direction.) -- with 1 optional parameter **name** to target a specific animation 
- **lottie.searchAnimations()** -- looks for elements with class "lottie" 
- **lottie.loadAnimation()** -- Explained above. returns an animation instance to control individually.
- **lottie.destroy()** -- To destroy and release resources. The DOM element will be emptied. 
- **lottie.registerAnimation()** -- you can register an element directly with registerAnimation. It must have the "data-animation-path" attribute pointing at the data.json url 
- **lottie.setQuality()** -- default 'high', set 'high','medium','low', or a number > 1 to improve player performance. In some animations as low as 2 won't show any difference. 

## Events
- onComplete
- onLoopComplete
- onEnterFrame
- onSegmentStart

you can also use addEventListener with the following events:
- complete
- loopComplete
- enterFrame
- segmentStart
- config_ready (when initial config is done)
- data_ready (when all parts of the animation have been loaded)
- DOMLoaded (when elements have been added to the DOM)
- destroy

#### Other loading options
- if you want to use an existing canvas to draw, you can pass an extra object: 'renderer' with the following configuration:
```js
lottie.loadAnimation({
  container: element, // the dom element
  renderer: 'svg',
  loop: true,
  autoplay: true,
  animationData: animationData, // the animation data
  rendererSettings: {
    context: canvasContext, // the canvas context
    scaleMode: 'noScale',
    clearCanvas: false,
    progressiveLoad: false, // Boolean, only svg renderer, loads dom elements when needed. Might speed up initialization for large number of elements.
    hideOnTransparent: true //Boolean, only svg renderer, hides elements when opacity reaches 0 (defaults to true)
  }
});
```
Doing this you will have to handle the canvas clearing after each frame

Another way to load animations is adding specific attributes to a dom element.
You have to include a div and set it's class to lottie.
If you do it before page load, it will automatically search for all tags with the class "lottie".
Or you can call lottie.searchAnimations() after page load and it will search all elements with the class "lottie".

- add the data.json to a folder relative to the html
- create a div that will contain the animation.

**Required**

- a class called "lottie"
- a "data-animation-path" attribute with relative path to the data.json

**Optional**

- a "data-anim-loop" attribute
- a "data-name" attribute to specify a name to target play controls specifically

**Example**

```html
<div style="width:1067px;height:600px" class="lottie" data-animation-path="animation/" data-anim-loop="true" data-name="ninja"></div>
```

# Previewing Animations

## 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 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.

# Expressions

Unfortunately, expressions are similar to javascript but not quite the same.
So for converting and evaluating the code, I use Esprima and Escodegen.
A subset of expressions is supported.

## Return value in the last line of code.
The returning value must be on the last line. You can't return the value in the middle code.
To workaround this, you can create a var, set the value, and return it in the final line.

## Expression controls
All expression controls are supported. You should have no issues linking any of the supported properties to an expression control.

## Native functions
functions like linear, velocityAtTime and wiggle are not supported.
Probably some will in the near future.
You can set your own function inside the code.

## Use javascript
If you set the string 'use javascript' as the first line of your expression, the plugin won't parse your code and you can get a significant performance increase.
For your code to be javascript compliant, please declare all vars and use operators limited to what javascript supports.
For example don't use an addition operator to sum two arrays.

## valueAtTime

Function `valueAtTime` can only be used in expressions when it is referencing the same property or other non-expression properties.
When calling this function for the other expression property, it will return base property values obtained from keyframes, not an expression result, as it happens in After Effects.
This may lead to some animations not working properly on export. 

For example, this causes issues when exporting [Duik](https://rainboxprod.coop/en/tools/duik/)'s forward kinematics. See [this issue](https://github.com/airbnb/lottie-web/issues/1661) for more information.

As a possible workaround, you can pre-bake expressions into keyframes before export by using `Convert expression to keyframes` feature of After Effects, or any baking plugin. 

# Troubleshooting

## Missing masks
For missing mask in Safari browser, please anim.setLocationHref(locationHref) before animation is generated. It usually caused by usage of base tag in html. (see above for description of setLocationHref)

## Cameras

You can use a 3d one-node or two-node Camera.
Camera options are not exportable. The idea of using a camera is to provide a moving point of view for the composition.
You can parent layers to the camera, but you can't parent the camera to any layer. It will probably be supported soon.

## Masks and 3d don't go well together on browsers.

So if you mask a layer it will lose it's 3d properties. What you can do, is use masks inside 3d comps that have 2d layers.

## Scaling and z axis.

If an element needs to be rendered larger than the original size, it won't be smoothed since browsers promote layers to hardware rendering as textures and they won't redraw them as vectors like the canvas and svg renderers do.

## Text
* Text boxes can't contain more than one style (AE doesn't expose multi font text layers).
* Many paragraph and character settings are not supported yet.
* 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.

---

## File: windows.md

# Getting Started

## Previewing Lottie JSON Files

Use the [Lottie Viewer application](https://aka.ms/lottieviewer) to test the visual accuracy of your Lottie animations and identify potential issues. 
Simply use drag-and-drop or use a file-picker to open local JSON files and URIs. A warning icon may light up to indicate any issues with your animation.



[](https://www.microsoft.com/store/apps/9p7x9k692tmw?ocid=badge)

## Using JSON 

To get started with Lottie-Windows, you will require:

*  Windows 10 SDK version 1809 (17763) or above
* [Microsoft.UI.Xaml nuget package](https://www.nuget.org/packages/Microsoft.UI.Xaml/) which contains the [AnimatedVisualPlayer](https://www.docs.microsoft.com/uwp/api/microsoft.ui.xaml.controls.animatedvisualplayer) XAML element
* [Microsoft.Toolkit.Uwp.UI.Lottie nuget package](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI.Lottie/) which produces a [LottieVisualSource](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.uwp.ui.lottie.lottievisualsource)

```xaml
    xmlns:lottie="using:Microsoft.Toolkit.Uwp.UI.Lottie"
    xmlns:winui="using:Microsoft.UI.Xaml.Controls"
```

You can now bring high-quality, resolution-independent vector animations to your Windows applications with just a couple of lines of XAML:

```xaml
    <!--  AnimatedVisualPlayer with AutoPlay  -->
    <winui:AnimatedVisualPlayer x:Name="LottiePlayer">
        <!--  LottieVisualSource that parses a JSON Uri at run-time  -->
        <lottie:LottieVisualSource UriSource="ms-appx:///AnimatedVisuals/LottieLogo1.json" />
    </winui:AnimatedVisualPlayer>
```

For detailed steps and code samples for getting started with a JSON file, check out [this tutorial](https://docs.microsoft.com/windows/communitytoolkit/animations/lottie-scenarios/getting_started_json).

## Using Codegen

In addition to using JSON files, Lottie-Windows allows you to use generated C# / C++ classes for better performance 
by avoiding the cost of parsing and translating JSON files at run-time. You may generate the code by using:

* [LottieGen command-line tool](https://aka.ms/lottiegen), or
* [Lottie Viewer application](https://github.com/windows-toolkit/Lottie-Windows/tree/master/LottieViewer#usage)

Having generated your C# or C++ class, you'll need to configure your AnimatedVisualPlayer to consume it:

```xaml
    <!--  AnimatedVisualPlayer with AutoPlay  -->
    <winui:AnimatedVisualPlayer x:Name="LottiePlayer">
        <!--  Codegen source with C# class: AnimatedVisuals/LottieLogo1.cs  -->
        <animatedvisuals:LottieLogo1 />
    </winui:AnimatedVisualPlayer>
```

For detailed steps and code samples for using codegen in lieu of JSON, check out [this tutorial](https://docs.microsoft.com/windows/communitytoolkit/animations/lottie-scenarios/getting_started_codegen).

## JSON versus Codegen

Both approaches — JSON and Codegen — produce the same visual results but have different tradeoffs and workflows; 
to decide which is best suited for your application, check out [this comparison](https://docs.microsoft.com/windows/communitytoolkit/animations/lottie-scenarios/json_codegen). Here's how all the pieces fit together:



# Tutorials

Here are [some tutorials](https://docs.microsoft.com/windows/communitytoolkit/animations/lottie#tutorials) to help you with 
common Lottie animation scenarios, including:

* [Getting started with JSON](https://docs.microsoft.com/windows/communitytoolkit/animations/lottie-scenarios/getting_started_json)
* [Using Codegen](https://docs.microsoft.com/windows/communitytoolkit/animations/lottie-scenarios/getting_started_codegen)
* [JSON versus Codegen](https://docs.microsoft.com/windows/communitytoolkit/animations/lottie-scenarios/json_codegen)
* [Configuring animation playback](https://docs.microsoft.com/windows/communitytoolkit/animations/lottie-scenarios/playback)
* [Interactive segments on an animation timeline](https://docs.microsoft.com/windows/communitytoolkit/animations/lottie-scenarios/segments)
* [Asynchronous Play method](https://docs.microsoft.com/windows/communitytoolkit/animations/lottie-scenarios/async_play)
* [Handling failure and down-level](https://docs.microsoft.com/windows/communitytoolkit/animations/lottie-scenarios/fallback)
    
## Code Samples

The [Lottie Samples application](https://aka.ms/lottiesamples) accompanies the tutorials by providing simple code examples. 
The source code for the samples may be [found here](https://github.com/windows-toolkit/Lottie-Windows/tree/master/samples).



[](https://www.microsoft.com/store/apps/9n3j5tg8ff7f?ocid=badge)

# Troubleshooting

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)

## Help and Feedback

Feel free to reach out to us with questions, feedback, and bug reports [via Github](https://github.com/windows-toolkit/Lottie-Windows/issues).

---

## File: .github/FUNDING.yml

open_collective: lottie

--- METRICS ---
- Files Extracted: 17
- Estimated Token Budget: ~35436 tokens
- Recency Window: Active (< 180 days)
- Canonical Reference: https://codewiki.google/github.com/airbnb/lottie
