How to add a color overlay to an animation in Lottie?
Asked Answered
J

7

25

I'm using Lottie for Android to add some animations in an app. In this app the primary and accent color can be chosen via the settings. I'm using an animation with a transparent background. To make the animation fit the chosen colors I'd like to add a color overlay to the animation, this way I can have one animation file but I can set the color programmatically.

Does anyone have an idea how I can manipulate the animation by adding a color overlay?

Jaeger answered 12/4, 2017 at 17:46 Comment(0)
J
58

To apply a color filter you'll need three things as of now:

  1. KeyPath (name of content you wish to edit)
  2. LottieProperty (name of property you wish to edit)
  3. LottieValueCallback (callback called for every animation re-render)

The layer name can be found in the JSON of the animation by the tag 'nm'.

Add a full color overlay:

LottieAnimationView animationView = findViewById(R.id.animation_view);
animationView.addValueCallback(
        new KeyPath("**"),
        LottieProperty.COLOR_FILTER,
        new SimpleLottieValueCallback<ColorFilter>() {
            @Override
            public ColorFilter getValue(LottieFrameInfo<ColorFilter> frameInfo) {
                return new PorterDuffColorFilter(Color.GREEN, PorterDuff.Mode.SRC_ATOP);
            }
        }
);

Add a single layer color overlay (layer called "checkmark"):

LottieAnimationView animationView = findViewById(R.id.animation_view);
animationView.addValueCallback(
        new KeyPath("checkmark", "**"),
        LottieProperty.COLOR_FILTER,
        new SimpleLottieValueCallback<ColorFilter>() {
            @Override
            public ColorFilter getValue(LottieFrameInfo<ColorFilter> frameInfo) {
                return new PorterDuffColorFilter(Color.CYAN, PorterDuff.Mode.SRC_ATOP);
            }
        }
);

Remove any color overlays:

LottieAnimationView animationView = findViewById(R.id.animation_view);
animationView.addValueCallback(new KeyPath("**"), LottieProperty.COLOR_FILTER,
        new SimpleLottieValueCallback<ColorFilter>() {
            @Override
            public ColorFilter getValue(LottieFrameInfo<ColorFilter> frameInfo) {
                return null;
            }
        }
);

You can read all about it in the official documentation.

You can also check out this sample repository

Here's a visual on the results of the code snippets:

Example

Jaeger answered 10/8, 2017 at 7:34 Comment(10)
use app:lottie_colorFilter="@color/colorAccent" in case you want to access via xmlIdolla
addColorFilter not defined in Lottie. check plzAffirm
Is it possible to overlay a gradient instead of a solid color?Inadequate
Link of " the official documentation." is dead. Here's an archived version of it: web.archive.org/web/20180731092340/http://airbnb.io:80/lottie/… . Maybe there is a newer link?Shreeves
@androiddeveloper thanks for the heads-up, I changed the URL to the newer version of the documentation.Jaeger
@Jaeger Say, can you please share a Github sample of how to color one part of the animation file? So far I've seen only changing color of the entire animation.Shreeves
@androiddeveloper I went out of my way and created a sample repository that shows the Lottie 3.0.0 implementation. I've also updated the answer. Here you are: github.com/SolveSoul/lottie-android-colorfilter-sampleJaeger
@Jaeger Thank you! Say, is there any difference between setting the color this way, and setting it using colorFilter? Performance hit?Shreeves
Is there any way to animate the change in color? In the example the animation starts off empty, but what if I wanted to change from the original checkmark to one of the others while it was animating?Delvecchio
@Delvecchio it's certainly possible but Lottie is being a bit flaky with reporting animation progress in the callback. Anyway, I added some sample code on how you could approach this: github.com/SolveSoul/lottie-android-colorfilter-sample/commit/…Jaeger
S
20

Found in sources of lottie, based on main answer (thanks @SolveSoul ).

Java

First, get your color, for example:

int yourColor = ContextCompat.getColor(getContext(),R.color.colorPrimary);

Then set color filter like this:

SimpleColorFilter filter = new SimpleColorFilter(yourColor);
KeyPath keyPath = new KeyPath("**");
LottieValueCallback<ColorFilter> callback = new LottieValueCallback<ColorFilter>(filter);
animationView.addValueCallback(keyPath, LottieProperty.COLOR_FILTER, callback);

Kotlin

First, get your color, for example:

val yourColor = ContextCompat.getColor(context, R.color.colorPrimary)

Then set color filter like this:

val filter = SimpleColorFilter(yourColor)
val keyPath = KeyPath("**")
val callback: LottieValueCallback<ColorFilter> = LottieValueCallback(filter)

animationView.addValueCallback(keyPath, LottieProperty.COLOR_FILTER, callback)

Kotlin extension

fun LottieAnimationView.changeLayersColor(
    @ColorRes colorRes: Int
) {
    val color = ContextCompat.getColor(context, colorRes)
    val filter = SimpleColorFilter(color)
    val keyPath = KeyPath("**")
    val callback: LottieValueCallback<ColorFilter> = LottieValueCallback(filter)

    addValueCallback(keyPath, LottieProperty.COLOR_FILTER, callback)
}

Stulin answered 19/7, 2018 at 11:5 Comment(0)
I
6

Compose + Lottie

@Composable
fun LottieAnimation(isPlaying: Boolean = false) {
    val composition by rememberLottieComposition(LottieCompositionSpec.Asset(LOTTIE_FILE_NAME))
    val progress by animateLottieCompositionAsState(
        composition,
        iterations = LottieConstants.IterateForever,
        isPlaying = isPlaying,
    )
    val dynamicProperties = rememberLottieDynamicProperties(
        rememberLottieDynamicProperty(
            property = LottieProperty.COLOR_FILTER,
            value = SimpleColorFilter(MaterialTheme.colors.primary.toArgb()),
            keyPath = arrayOf("**")
        ),
    )
    LottieAnimation(
        composition = composition,
        progress = { progress },
        dynamicProperties = dynamicProperties,
    )
}
Ingraham answered 2/11, 2022 at 13:6 Comment(0)
T
5

Since you're passing a JSONObject containing all of the drawing data to Lottie when setting the animation, you could just replace some of the color values with your desired ones before you set it.

If you look for the color key c you'll probably find something like

...,"c":{"k":[1,0.7,0,1]},"fillEnabled":true,...

where changing those float values in that JSONArray would change the colors in the animation.

Granted, I'm not saying it will be too trivial to find/replace the correct values, but this should at least point you in that direction.

As a side note: once you find it, you could set the value in your asset to some kind of nice placeholder like "k":[ BG_COLOR_REPLACEMENT_1 ] and then when loading the asset, just run .replace("BG_COLOR_REPLACEMENT_1", "1,0.7,1,1"); on your String before creating the JSONObject and passing it to Lottie.

Topdrawer answered 12/4, 2017 at 18:19 Comment(0)
B
3

I saw Guardanis answer and elaborated a safe way to find the colour inside the JSON that contains the Lottie animation:

Search for - "c":{"a" - and you will find fragments like this for each layer of you image: {"ty":"fl","c":{"a":0,"k":[0.4,0.4,0.4,0.4]}

In the fragment you will notice "c" means COLOUR, "a" means ALPHA and "k" is the CMYK of the colour of the layer. Just change it for the one that you want.

Bate answered 26/4, 2018 at 19:0 Comment(2)
Just be wary that a JSONObject is an unordered mapping concept, and that those a and k keys may not appear lexicographically in your search. Spaces and newlines may also be the result of pretty-printing, so you may want to normalize it before searching and using regular expressions.Topdrawer
actually seems to be HSV colour code for me, not sure what the 4th value does though, playing in a preview doesn't seem to change anythingDonell
C
2

In Kotlin(v1.4.32) To set up full animation in all layers just do this :

YOURS_LottieAnimationView.addValueCallback(
            KeyPath("**"),
            LottieProperty.COLOR_FILTER,
            { PorterDuffColorFilter(Color.parseColor("#b70101"), PorterDuff.Mode.SRC_ATOP) }
        )
Coronation answered 20/4, 2021 at 10:54 Comment(0)
I
-3

If your JSON has has an sc: field then you should be able to set the Hex color directly

like:

"sc": "#6664e7"
Indohittite answered 4/7, 2019 at 15:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.