Jump to content
Search Community

Restart and play again animation on state change. (With useEffect)

Argi test
Moderator Tag

Go to solution Solved by Argi,

Recommended Posts

Hi there !
I have some problem with GSAP animations.

To give you some my code understanding i gonna tell u what i want to achieve.

So i have on my page 2 languages to chose and u chose it by pressing the button.

When you click the button my page content is changing - my pageContent is an object, and it is a state which is changing depends on chosen language.

 

And here is my problem:
I'm using react hook useEffect to trigger animation, so my animation will start on pageContent change (so basically on language change)

// Animation trigger
    useEffect(()=>  {
        //Check if data exists, if data not exists page will not animate which will prevent from causing gsap errors
        if(pageContent === undefined || pageContent === null ) {return};
        animatePage();
      
    }, [ pageContent ]);

Animation function look like that:

 // Animate Page Function
    function animatePage() {
        // Get elements to animate 
        const contact = document.getElementsByClassName('contact');
        const contactDetails = document.getElementById('contact-details');
        const contactH = document.getElementById('contact-h');
        const field1 = document.getElementById('field1');
        const field2 = document.getElementById('field2');
        const field3 = document.getElementById('field3');
        const field4 = document.getElementById('field4');
        const btnContact = document.getElementById('btn-contact');
        const mapContainer = document.getElementById('map-container');



        // Setup
        gsap.set([contact,contactDetails,contactH, field1, field2, field3, field4, btnContact, mapContainer], {autoAlpha: 0, opacity: 0});

         // Animation
         pageTl
         .fromTo(contact, {opacity: 0, autoAlpha: 0}, {delay: .1, duration: .1, opacity: 1, autoAlpha: 1})
         .fromTo(contactDetails, {y: '-=150'}, {duration: .2, opacity: 1, autoAlpha: 1,y: '+=150'})
         .fromTo(contactH, {y: '-=150'}, {duration: 1, opacity: 1, autoAlpha: 1,y: '+=150'})
         .fromTo(field1, {y: '+=300'}, {duration: .44, y: '-=300', autoAlpha: 1}, '-=0.15')
         .fromTo(field2, {y: '+=300'}, {duration: .44, y: '-=300', autoAlpha: 1}, '-=0.15')
         .fromTo(field3, {y: '+=300'}, {duration: .44, y: '-=300', autoAlpha: 1}, '-=0.15')
         .fromTo(field4, {y: '+=300'}, {duration: .44, y: '-=300', autoAlpha: 1}, '-=0.15')
         .fromTo(btnContact, {y: '+=300'}, {duration: .44, y: '-=300', autoAlpha: 1}, '-=0.15')
         .fromTo(mapContainer, {y: '+=1000'}, {duration: .8, y: '-=1000', autoAlpha: 1}, '-=0.8')
     };

 

The problem is - if i gonna press the language button before animation will end whole animation gonna broke and what i mean by that is; the elements which are animating will no appear where they should at the end.

I was trying to use .restart() and .kill() but probably im doing something wrong because it's not working for me. I was trying to fix it by a long time so i would be pleased if someone could help me with that.

How can i restart this animation ?


Sorry if my english is not as good as it could be :P

Regards, Kamil.

Link to comment
Share on other sites

Hey Kamil and welcome to the GreenSock forums.

 

This is a logical issue. Since you have a += as your starting (fromVars) values, it will use whatever the current value is at that time. If the user clicks before the animation is finished, the new starting value is based on the in-progress value. So it ends up in a place that you don't want.

 

There are a lot of ways to fix this issue. I think the easiest would be to clear out the values before you create your timeline again. Something like this:

// Kill old animation
if(pageTl) pageTl.kill()

// Setup
gsap.set([contact, contactDetails, contactH, field1, field2, field3, field4, btnContact, mapContainer], {
  autoAlpha: 0, 
  y: 0
});

// Animation
pageTl = gsap.timeline({ defaults: { duration: .44 } })
  .to(contact, {duration: .1, autoAlpha: 1}, 0.1)
  .fromTo(contactDetails, {y: '-=150'}, { duration: .2, autoAlpha: 1 })
  .fromTo(contactH, {y: '-=150'}, { duration: 1, autoAlpha: 1 })
  .fromTo(field1, {y: '+=300'}, { autoAlpha: 1 }, '-=0.15')
  .fromTo(field2, {y: '+=300'}, { autoAlpha: 1 }, '-=0.15')
  .fromTo(field3, {y: '+=300'}, { autoAlpha: 1 }, '-=0.15')
  .fromTo(field4, {y: '+=300'}, { autoAlpha: 1 }, '-=0.15')
  .fromTo(btnContact, {y: '+=300'}, { autoAlpha: 1 }, '-=0.15')
  .fromTo(mapContainer, {y: '+=1000'}, { duration: .8, autoAlpha: 1 }, '-=0.8')

Sides notes:

  • There's no point animating opacity and autoAlpha. Just use autoAlpha.
  • Your usage of '+=' in the fromVars and '+=' in the toVars doesn't make much sense. Most likely you can leave out the y in the toVars because it will go to the value it was at the start. More on that in my article about animating efficiently.
  • You'd probably benefit from using timeline defaults like I did in the code above.

Note that the code above is untested given you didn't provide a minimal demo.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

  • Solution
On 2/1/2021 at 6:35 PM, ZachSaucier said:

Hey Kamil and welcome to the GreenSock forums.

 

This is a logical issue. Since you have a += as your starting (fromVars) values, it will use whatever the current value is at that time. If the user clicks before the animation is finished, the new starting value is based on the in-progress value. So it ends up in a place that you don't want.

 

There are a lot of ways to fix this issue. I think the easiest would be to clear out the values before you create your timeline again. Something like this:



// Kill old animation
if(pageTl) pageTl.kill()

// Setup
gsap.set([contact, contactDetails, contactH, field1, field2, field3, field4, btnContact, mapContainer], {
  autoAlpha: 0, 
  y: 0
});

// Animation
pageTl = gsap.timeline({ defaults: { duration: .44 } })
  .to(contact, {duration: .1, autoAlpha: 1}, 0.1)
  .fromTo(contactDetails, {y: '-=150'}, { duration: .2, autoAlpha: 1 })
  .fromTo(contactH, {y: '-=150'}, { duration: 1, autoAlpha: 1 })
  .fromTo(field1, {y: '+=300'}, { autoAlpha: 1 }, '-=0.15')
  .fromTo(field2, {y: '+=300'}, { autoAlpha: 1 }, '-=0.15')
  .fromTo(field3, {y: '+=300'}, { autoAlpha: 1 }, '-=0.15')
  .fromTo(field4, {y: '+=300'}, { autoAlpha: 1 }, '-=0.15')
  .fromTo(btnContact, {y: '+=300'}, { autoAlpha: 1 }, '-=0.15')
  .fromTo(mapContainer, {y: '+=1000'}, { duration: .8, autoAlpha: 1 }, '-=0.8')

Sides notes:

  • There's no point animating opacity and autoAlpha. Just use autoAlpha.
  • Your usage of '+=' in the fromVars and '+=' in the toVars doesn't make much sense. Most likely you can leave out the y in the toVars because it will go to the value it was at the start. More on that in my article about animating efficiently.
  • You'd probably benefit from using timeline defaults like I did in the code above.

Note that the code above is untested given you didn't provide a minimal demo.

 

 

 

 

 

Hi! 

Thank you for your response, thanks to you i made my code a bit shorter. I saw someone on youtube who is recommending to use both (opacity and autoalpha) for sure, but if you telling me there is no sense - it's even better for me :)

Thanks also for advise of using defaults values.

So if i understand well i need to use fromVars but i dont need to use toVars if i put them to the defaults ?
Could you explain me how gsap.set works ? Where is the different between that and defaults?

As i said, my code looks better now but the solution didn't work for me, and it's hard to put the demo (it would take too much time). I figured it out on my own  - the problem was in useEffect dependencies but it's hard to explain without the code :)


Could you gave me some example of reseting animation ? What i mean by that:

For example i have a hamburger menu and it's hide/show on hamburger button click. How to avoid gsap animation collapse if someone would still clicking the hamburger button ? 

Regards!

Link to comment
Share on other sites

40 minutes ago, Argi said:

i need to use fromVars but i dont need to use toVars if i put them to the defaults ?

It depends on the situation and what you need to animate from and to. You should use whatever method that you need at the appropriate time, whether it's .set(), .from(), .fromTo(), or .to(). 

 

41 minutes ago, Argi said:

Could you explain me how gsap.set works ?

Reading the docs is probably the best way to learn :) .set() sets the properties at that time.

 

42 minutes ago, Argi said:

Where is the different between that and defaults?

Defaults are just that - default values for tweens. They don't do anything unless you have a tween that the default gets applied to. And if you have the same property declared inside of a tween, it will overwrite the default value. Again, I encourage you to read about them :) 

 

43 minutes ago, Argi said:

i have a hamburger menu and it's hide/show on hamburger button click. How to avoid gsap animation collapse if someone would still clicking the hamburger button ? 

There are various ways to do that sort of thing. As covered in my article about animating efficiently that I said you should read earlier, most of the time creating animations beforehand and using control methods is the way to go. Other times it might be appropriate to overwrite your old animations and make sure that you animate to the correct end values. 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

On 2/2/2021 at 6:09 PM, ZachSaucier said:

It depends on the situation and what you need to animate from and to. You should use whatever method that you need at the appropriate time, whether it's .set(), .from(), .fromTo(), or .to(). 

 

Reading the docs is probably the best way to learn :) .set() sets the properties at that time.

 

Defaults are just that - default values for tweens. They don't do anything unless you have a tween that the default gets applied to. And if you have the same property declared inside of a tween, it will overwrite the default value. Again, I encourage you to read about them :) 

 

There are various ways to do that sort of thing. As covered in my article about animating efficiently that I said you should read earlier, most of the time creating animations beforehand and using control methods is the way to go. Other times it might be appropriate to overwrite your old animations and make sure that you animate to the correct end values. 

 

Thank you for your time.
I have a lot of questions, but its not for this theard.

I think we can close this one :)

Regards

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...