Jump to content
Search Community

How do I avoid undesired effects when creating multiple animations?

chrisandrew test
Moderator Tag

Recommended Posts

Hi!

 

First-time poster, please let me know if I can do anything to improve future questions.

 

In the attached pen, I'm tweening the card title to follow the cursor on mouseover. In isolation, it works as I would expect. However, the behaviour changes dramatically when any arbitrary tween is applied to the card containing the title.

 

I often encounter similar difficulty to avoid undesired effects, as well as issues with things like stacking context. I think I'm missing something critical about where, when and how to create and use multiple tweens correctly. Any guidance would be much appreciated.

 

 

See the Pen vYrNxwq?editors=0010 by chrisandrew_dev (@chrisandrew_dev) on CodePen

Link to comment
Share on other sites

Hi @chrisandrew welcome to the forum! This question is great! You've have a demo and a clear description, those are the once we love!

 

I still need to dive in to how it works my self, but have you seen the .quickSetter() function. Sounds exactly like what you want, but personally I've never used it myself. Hope these resources help!

 

If you find yourself calling gsap.set() many times on the same object (or set of objects), like in a "mousemove" event, you can boost performance 50% - 250% by creating a quickSetter function and using that instead of gsap.set(). Think of a quickSetter like an optimized function tied to a particular target's (or set of targets') property, where it directly pipes data to it and skips convenience tasks in a normal gsap.set() call such as:

 

https://greensock.com/docs/v3/GSAP/gsap.quickSetter()

 

See the Pen WNNNBpo?editors=0010 by GreenSock (@GreenSock) on CodePen

  • Like 2
Link to comment
Share on other sites

5 hours ago, chrisandrew said:

However, the behaviour changes dramatically when any arbitrary tween is applied to the card containing the title.

 

I often encounter similar difficulty to avoid undesired effects, as well as issues with things like stacking context. I think I'm missing something critical about where, when and how to create and use multiple tweens correctly. Any guidance would be much appreciated.

It has nothing to do with a tween being applied - it's simply that whenever there is ANY transform applied to an element (even translate(0px, 0px)), it creates a new stacking context which affects the offsetTop/offsetLeft in your calculations. Those are measured from the first ancestor that has a stacking context or non-static position. 

 

It's also a very bad idea to apply CSS transitions to something that you're using GSAP to animate. It's terrible for performance in most cases since they're kinda fighting with each other over the same property of the same element. 

 

Performance-wise, the way you're doing it is somewhat costly because you're calculating offsetLeft/offsetTop/offsetWidth/offsetHeight and also querySelector() on EVERY mousemove. Here's how I'd do it in a more performant way that isn't thrown off by transforms: 

See the Pen MWXarPm?editors=0010 by GreenSock (@GreenSock) on CodePen

 

Does that help? 

  • Like 2
Link to comment
Share on other sites

8 hours ago, mvaneijgen said:

I still need to dive in to how it works my self, but have you seen the .quickSetter() function...If you find yourself calling gsap.set() many times on the same object (or set of objects), like in a "mousemove" event, you can boost performance 50% - 250% by creating a quickSetter function and using that instead of gsap.set().

 

Thanks, @mvaneijgen. I understand that there's room for optimisation in the pen however the pen only serves to demonstrate that when a second animation (in this case gsap.to('.card', { y: 100 })) is applied, the first tween (on mouseover) 'breaks'. 

Link to comment
Share on other sites

2 hours ago, GreenSock said:

It has nothing to do with a tween being applied - it's simply that whenever there is ANY transform applied to an element (even translate(0px, 0px))...

 

It's also a very bad idea to apply CSS transitions to something that you're using GSAP to animate. It's terrible for performance in most cases since they're kinda fighting with each other over the same property of the same element. 

 

Performance-wise, the way you're doing it is somewhat costly because you're calculating offsetLeft/offsetTop/offsetWidth/offsetHeight and also querySelector() on EVERY mousemove. Here's how I'd do it in a more performant way that isn't thrown off by transforms:  

Thanks @GreenSock Jack, I really appreciate you taking the time to respond.

 

I'm not transforming any elements in my demo but I can absolutely replace CSS transitions with GSAP eases. Regarding performance etc, my pen is merely intended for demonstration purposes. I understand and agree that there's room for optimisation in production.

 

Applying a tween to a card (gsap.to('.card', { y: 100 })) 'breaks' the tween applied to the card title. I'm still not clear why this is the case or how to avoid it. That is the specific problem I am trying to solve (and more importantly, understand). Apologies I didn't communicate more clearly.

Link to comment
Share on other sites

4 hours ago, chrisandrew said:

Applying a tween to a card (gsap.to('.card', { y: 100 })) 'breaks' the tween applied to the card title. I'm still not clear why this is the case or how to avoid it. That is the specific problem I am trying to solve (and more importantly, understand). Apologies I didn't communicate more clearly.

I explained why in my original response. It has absolutely nothing to do with a tween or GSAP - it's just how CSS/browsers work. If you apply a transform of any kind (which is what you were doing by animating the "y" property - transform: translateY()), it creates a new stacking context which affects the offsetTop/offsetLeft measurements. Your calculations were based on the assumption that the parent wouldn't have its own stacking context which is a faulty assumption. See what I mean?

 

This is why I spent a fair amount of time reworking your demo for you. Did you notice it works perfectly regardless of whether or not you have a transform applied? Give it a try. I even added code to handle the case where the user scrolls while hovered (your original broke in that case too). I basically provided a plug-and-play solution. 

 

Did you look at the code in my demo? 

Link to comment
Share on other sites

1 hour ago, GreenSock said:

If you apply a transform of any kind (which is what you were doing by animating the "y" property - transform: translateY()), it creates a new stacking context which affects the offsetTop/offsetLeft measurements.

@GreenSock Jack, 

Gotcha, I misunderstood you as referring to CSS transforms, I didn't realise you were referring to animating the 'y' property in the tween.

 

1 hour ago, GreenSock said:

This is why I spent a fair amount of time reworking your demo for you. Did you notice it works perfectly regardless of whether or not you have a transform applied? Give it a try.

Thank you again for that. I had mixed results (maybe something to do with Chrome?). There were instances when 1-2 cards wouldn't respond on mouseover. I'll see if I can work out why.

 

1 hour ago, GreenSock said:

I even added code to handle the case where the user scrolls while hovered (your original broke in that case too). Did you look at the code in my demo? 

TBH, the necessity of this logic threw me a little. It makes more sense now.

 

I'll have a go at implementing your solution in React (the production codebase is React). I really appreciate the time you've taken to help.

  • Like 1
Link to comment
Share on other sites

13 hours ago, chrisandrew said:

Gotcha, I misunderstood you as referring to CSS transforms, I didn't realise you were referring to animating the 'y' property in the tween.

That's exactly what I was referring to - CSS transforms. When you animate the "y" property, that's simply affecting the transform: translateY(). Doesn't matter if it's animated or not - try adding even just transform: translate(0px, 0px) in your CSS to that container element and you'll get the same result. 

 

14 hours ago, chrisandrew said:

Thank you again for that. I had mixed results (maybe something to do with Chrome?). There were instances when 1-2 cards wouldn't respond on mouseover. I'll see if I can work out why.

I'm super curious to see a minimal demo where it doesn't work. Would you mind providing one or give the steps needed for reproducing it in the demo I provided? 

 

14 hours ago, chrisandrew said:

TBH, the necessity of this logic threw me a little. It makes more sense now.

Yeah, roll your mouse over one, stop, then (while stopped) scroll with your mouse wheel. That's what I was talking about. 

 

14 hours ago, chrisandrew said:

I'll have a go at implementing your solution in React (the production codebase is React). I really appreciate the time you've taken to help.

Sounds good. 👍

  • Like 1
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...