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).
We are working on it!
+1
Is there a way to access a layer by name in Swift in order to manipulate properties such as color directly on the CALayer?
any updates with this issue?
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.
Should be out this week!
Stay tuned!
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];
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.
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.
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!
I should probably add some logging of warnings instead of the crash for wrong keypaths.
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 馃憤
Duplicate of # How u got to know the layer name
@chaitanya-ramji Yes! If you initialize a LOTAnimaitonView with your animation and call logHierarchyKeypaths it will print all available keypaths into the console.
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.
Hmmm. I think that theres something wrong with logHierarchyKeypaths, clearly its missing some information. Do you have access to the after effects file?
Thanks for your response.
No, actually I don't have access. I have the JSON file only.
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.'
@RishabhTayal did you ever get it to work?
@ben5516 No I did not.
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.
Also FYI everyone a new api has been built for this and will replace the existing one in the next release (2.5)
Most helpful comment
We are working on it!