airbnb / lottie-web

Render After Effects animations natively on Web, Android and iOS, and React Native. http://airbnb.io/lottie/
MIT License
30.38k stars 2.87k forks source link

time remapping controlled from js? #1547

Closed saruzaru closed 5 years ago

saruzaru commented 5 years ago

I have an animation with text where each letter (about 15) should react to the cursor. I want to control these letters(precomps) with time remapping but i don't know how to access or change this property from js. I usually just use GSAP for js animation, could I use this to change the remap value? If yes, how?

bodymovin commented 5 years ago

you can use the lottie-api library to control properties from layers: https://github.com/bodymovin/lottie-api

saruzaru commented 5 years ago

ah, awesome! didn't know this existed. and i thought i looked everywhere in the docs.

so: var positionProperty = animationAPI.getKeyPath('red_solid,Transform,Position'); is this what i need to get to the time remapping property?

saruzaru commented 5 years ago

ugh, i can't get this to work. i'm an animator with basic knowledge of js, where can i find more examples for the api, or how can i get the property for time remapping or a slider effect? animationAPI.getKeyPath('letter_N,TimeRemap'); is this right? i adapted the basic example to this but nothing changes

bodymovin commented 5 years ago

I think you are missing a space letter_N,Time Remap. If you have a link with your implementation I can try to check it out. Here is a codepen example that uses lottie-api exhaustively. https://codepen.io/airnan/pen/gvBMPV

saruzaru commented 5 years ago

oh wow, why did i assume i had to take out the spaces? damn you CamelCase!! Thanks!

falls2lawrence commented 5 years ago

Could one of you please provide a simple example of javascript controlling time remapping to play a single element of the svg? For instance, a mouseover event on #bluecircle causes the time remap of bluecircle_comp to advance from 0:00:00:00 to 0:00:04:00 (names and timing aren't important, i'm just trying to understand how this works).

when it comes to interacting with bodymovin animations, these GitHub questions seem to be the only good place to learn and being able to control timelines of nested comps individually would open up whole new worlds of fun but i'm having a hard time figuring out how to put these lottie api pieces together and the chameleon codepen is a lot to take in.

saruzaru commented 5 years ago

hi lawrence, here's how i would do it:

function lottieInit() {
     var circleButton = document.getElementById("bluecircle");
     var timeRemap = 0;
     var remapProgressObj = {remapProgress:0};
     var animationAPI = lottie_api.createAnimationApi(myLottieAnimation);
     var timeRemapCircle = animationAPI.getKeyPath('bluecircle_comp,Time Remap');

     animationAPI.addValueCallback(timeRemapCircle, function(currentValue) { return timeRemap; });

     //i used GSAP TimelineMax but you can use anything you're comfortable with that can animate a float value
     var circleRemapTL = new TimelineMax({onUpdate:CircleAnimSetProgress, paused:true});
     circleRemapTL.fromTo(remapProgressObj,1,{remapProgress:0},{remapProgress:4,ease:Power0.easeNone});

     function CircleAnimSetProgress() { timeRemap = remapProgressObj.remapProgress; };

     circleButton.addEventListener("mouseover", function(evt) {
         TweenMax.to(circleRemapTL,1,{progress:1, ease:Power2.easeOut});
     };
     circleButton.addEventListener("mouseout", function(evt) {
         TweenMax.to(circleRemapTL,0.5,{progress:0, ease:Power1.easeOut});
     };
};
myLottieAnimation.addEventListener( "DOMLoaded", lottieInit);
falls2lawrence commented 5 years ago

Thanks for taking the time to write this out. I took some time fiddling with it but couldn't get it to work. It seems like the timeRemap variable is supposed to update when played but I'm finding it stays at 0. I'm too new at js.

saruzaru commented 5 years ago

you could just test out the timeRemap with some setTimeout where you just set it manually to some value(between 0 and 4 if the clip is 4 seconds long). if it still doesn't work then the problem is with the lottie api or the getkeypath. otherwise it might be some problem with the easing engine(GSAP)

saruzaru commented 5 years ago

when it wasn't working for me, it was because the getKeyPath() string wasn't written properly. maybe it's the same issue

falls2lawrence commented 5 years ago

Something like that must be the issue. Nothing seems to be affecting the nested timeline.

This is what I've been messing with. Kept it stupid simple. If you're willing to give it a look and see why it's not working for me, it would be much appreciated. https://drive.google.com/open?id=1NPb1RKLoo3vqUis_VVzeAAvp4hiK9QO3

bodymovin commented 5 years ago

@falls2lawrence hi, there is a couple of things you need to adjust:

falls2lawrence commented 5 years ago

Thanks. You definitely answered a few things I was unsure about. It's funny/embarrassing, I had tried every variation with no luck over the last week. Started with a slider driving remapping, then just remapping, then a square with no remap and a circle with remap to try both, I had tried with and without #. Anyway, today it is working and it's really exciting.

Question: where did "remapProgress" come from? Obviously it's important to this bit of code but I haven't yet found it in lottie or GreenSock. where can I read up on this?

bodymovin commented 5 years ago

@falls2lawrence remapProgress is just an arbitrary name set as a property of the remapProgressObj so GSAP can interpolate between the initial and final values