Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to replace colors #236

Closed
Johennes opened this issue May 15, 2017 · 22 comments
Closed

Add option to replace colors #236

Johennes opened this issue May 15, 2017 · 22 comments

Comments

@Johennes
Copy link
Contributor

The Android SDK (https://github.com/airbnb/lottie-android) seems to have support for replacing colors in an animation through filters. Would be nice to get the same functionality for the iOS SDK. One use case would be if you want to use the same animation in several different apps with distinct branding and colors. Currently this can only be achieved by having duplicated JSONs (overhead) or hot-swapping the colors in the JSON string at runtime (brittle).

@buba447
Copy link
Collaborator

buba447 commented Jun 13, 2017

We are working on it!

@pixeldock
Copy link

+1

@pwwilson
Copy link

Is there a way to access a layer by name in Swift in order to manipulate properties such as color directly on the CALayer?

@bduyng
Copy link

bduyng commented Aug 2, 2017

any updates with this issue?

@pwwilson
Copy link

pwwilson commented Aug 2, 2017

So far I have only been able to accomplish this in a round-about way which looks something like:
let innerLayers = lottieView.layer.sublayers?[0].sublayers?[0].sublayers?[0].sublayers?[0].sublayers?[0].sublayers

To find the highest level of layers. and then targeting the specific layer I want to change the color of with something like:
let outerCircleLayer = innerLayers![3].sublayers?[0]

and then finding the inner CAShapeLayer using:
let outerCircleShapeLayer:CAShapeLayer = outerCircleLayer?.sublayers?[0].sublayers?[0] as! CAShapeLayer

and then finally setting the color:
outerCircleShapeLayer.fillColor = pinColor.cgColor

It works but is less than ideal and may need to be restructured if the JSON changes.

@buba447
Copy link
Collaborator

buba447 commented Aug 2, 2017

Should be out this week!
Stay tuned!

@buba447
Copy link
Collaborator

buba447 commented Aug 2, 2017

Version 2 is out and you can now dynamically change ANY attribute at runtime.

Example:
[lottieAnimation setValue:[UIColor greenColor] forKeypath:@"Layer 1.Shape 1.Fill 1" atFrame:@0];

@buba447 buba447 closed this as completed Aug 2, 2017
@pwwilson
Copy link

pwwilson commented Aug 3, 2017

UPDATE: I realized I was missing the key ".Color" that's value is changing at the end. So the following works!
lottieView.setValue(UIColor.red, forKeypath: "Location Marker.Outer circle.outer_circle_fill.Color", atFrame: 0)


I'm getting an error while attempting to change the fill colors in my Lottie Animation using this new feature:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFString replaceCharactersInRange:withString:]: Range or index out of bounds'
This occurs when attempting to target fills like this:
lottieView.setValue(UIColor.red, forKeypath: "Location Marker.Outer circle.outer_circle_fill", atFrame: 0)
The JSON is as follows:
https://gist.github.com/WasabiMonster/d9b30f02a9d4f6755ea8d062aac9b2c0
It seems like it is not finding an interpolator in LOTAnimatorNode setValue:forKeyAtPath:forFrame
for the fill.

@pwwilson
Copy link

pwwilson commented Aug 3, 2017

One more notable issue I'm having with this latest feature, that wasn't occurring before, is now that I'm targeting multiple fills in the JSON (i.e. outer_circle_fill and inner_circle_fill) and multiple Lottie instances I am having problems retaining the set color after playing the animation. I have multiple instances of Lottie on a map at a time and colors set on one instance often switch to a color on another instance after the animation plays. This occurs even when I attempt to set every frame with the color (using a for loop.)

Basically the fill color that I set using setValue changes to another color after I play the animation. This incorrect color appears to be coming from colors that are set on other Lottie instances on the screen and not the color I set for that particular instance.

@buba447
Copy link
Collaborator

buba447 commented Aug 3, 2017

You need to include the property to change in the keypath
"Location Marker.Outer circle.outer_circle_fill"
should be
"Location Marker.Outer circle.outer_circle_fill.Color"
Since we allow you to change more than just the color on ios.

I just fixed the instance color bug in 2.0.2!

@buba447
Copy link
Collaborator

buba447 commented Aug 3, 2017

I should probably add some logging of warnings instead of the crash for wrong keypaths.

@buba447 buba447 reopened this Aug 3, 2017
@buba447 buba447 closed this as completed Aug 4, 2017
@chaitanya-ramji
Copy link

chaitanya-ramji commented Aug 21, 2017

Quick question, how would I know the layer names if I were to change the color of the keyPaths? Is there any method I can call to find out the keyPaths in Swift?

Edit: Got the solution. Thanks anyways 👍

@ehabnaim
Copy link

Duplicate of # How u got to know the layer name

@buba447
Copy link
Collaborator

buba447 commented Aug 23, 2017

@chaitanya-ramji Yes! If you initialize a LOTAnimaitonView with your animation and call logHierarchyKeypaths it will print all available keypaths into the console.

@MEnnabah
Copy link

MEnnabah commented Oct 12, 2017

I'm trying to call
setValue(ViewID.redColor!, forKeypath: "Shape Layer 1.Ellipse 1.Fill 1.Color", atFrame: 0)
but I'm getting
[LOTAnimationView setValue:forKeypath:atFrame:]: Keypath Not Found: Shape Layer 1.Ellipse 1.Fill 1.Color
This is the logged keypaths where I got "Shape Layer 1.Ellipse 1.Fill 1.Color" from:

2017-10-12 16:06:05.511405+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Transform.Scale
2017-10-12 16:06:05.511628+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Transform.Position
2017-10-12 16:06:05.511785+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Transform.Anchor Point
2017-10-12 16:06:05.511973+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Transform.Rotation
2017-10-12 16:06:05.512127+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Transform.Opacity
2017-10-12 16:06:05.512310+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Fill 1.Color
2017-10-12 16:06:05.512445+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Fill 1.Opacity
2017-10-12 16:06:05.512661+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Path 1.Path
2017-10-12 16:06:05.512787+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Transform.Scale
2017-10-12 16:06:05.512903+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Transform.Position
2017-10-12 16:06:05.513033+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Transform.Anchor Point
2017-10-12 16:06:05.513377+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Transform.Rotation
2017-10-12 16:06:05.513686+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Transform.Opacity
2017-10-12 16:06:05.513951+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Fill 1.Color
2017-10-12 16:06:05.514182+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Fill 1.Opacity
2017-10-12 16:06:05.514349+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Path 1.Path
2017-10-12 16:06:05.514713+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Transform.Scale
2017-10-12 16:06:05.515489+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Transform.Position
2017-10-12 16:06:05.515658+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Transform.Anchor Point
2017-10-12 16:06:05.515871+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Transform.Rotation
2017-10-12 16:06:05.516268+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Transform.Opacity
2017-10-12 16:06:05.516566+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Fill 1.Color
2017-10-12 16:06:05.516991+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Fill 1.Opacity
2017-10-12 16:06:05.517232+0200 MyApp[8591:491896] |Shape Layer 1.Ellipse 1.Path 1.Path

I'm also not sure which keypath to choose.

@buba447
Copy link
Collaborator

buba447 commented Oct 12, 2017

Hmmm. I think that theres something wrong with logHierarchyKeypaths, clearly its missing some information. Do you have access to the after effects file?

@MEnnabah
Copy link

MEnnabah commented Oct 16, 2017

Thanks for your response.
No, actually I don't have access. I have the JSON file only.

@RishabhTayal
Copy link
Contributor

Is there a way to get the value using keyValuePath? I am trying to get the position of the layer programatically.

I tried animationView.value(forKeyPath: "layer.Rectangle 1.Transform.Position"), but it crashes with reason *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<LOTAnimationView 0x7f842ec62e50> valueForUndefinedKey:]: this class is not key value coding-compliant for the key layer.'

@ben5516
Copy link

ben5516 commented Jan 11, 2018

@RishabhTayal did you ever get it to work?

@RishabhTayal
Copy link
Contributor

@ben5516 No I did not.

@buba447
Copy link
Collaborator

buba447 commented Jan 11, 2018

You're missing the atFrame: part of the method. @RishabhTayal Oh wait I see you are trying to get the value. The new API will give you the value.

@buba447
Copy link
Collaborator

buba447 commented Jan 11, 2018

Also FYI everyone a new api has been built for this and will replace the existing one in the next release (2.5)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants