Jump to content


Animating relative to current position

Moderator Tag

Recommended Posts

I'm trying to figure out how the relativity works when using the following for example.

.to(stageRef.current, {x: '+=' + itemWidthRef.current, duration: 1, ease: "expo.inOut"})

As you can see I am animating x relative to the current position using '+='.


My problem is that after a window resize along the x axis it causes this animation to jump before it starts moving, could it be the case that when I resize the window that GSAP still thinks my element is in the same position?


This may sound unusual but the reason why I think this is happening is that I have a window resize function which recenters and resizes things, this is a carousel basically and I want it to not be out of proportion on window resize so I am recalculating all the slide dimensions and the full width of the carousel.


I'm working in React so was hoping I could try this initial question first in the hope it may be something obvious, and then if more info is needed I will try recreate in codesandbox or something.






Link to comment
Share on other sites

When a tween renders for the first time, it records the starting and ending values internally so that it can interpolate between them SUPER fast (we obsess about performance around here). If, for example, your element's "x" is 0 when you created that tween and itemWidthRef.current is 500, then of course it would record that internally and start animating from 0 to 500. If the window resizes halfway through that tween, nothing changes for GSAP. There's no way it could possibly know that itemWidthRef.current changed since you fed it in as a string anyway. Plus it would significantly degrade performance if it had to check that end value on every tick and re-configure the interpolation. So it'll just keep going with the original values, ending at 500 as requested.


So if you want to alter where that element is animating to when the window resizes, you can do any of the following:

  1. Create a new tween accordingly with the new end value. Simple and clean. It's best to set overwrite: "auto" or overwrite: true so that the old one doesn't keep running and conflict. 
  2. invalidate() the original tween to force it to flush its start/end values and re-record them on the very next render. You'd also need to use a function-based value to make it dynamic, like x: () => "+=" + itemWidthRef.current. Also beware that if you want to keep the starting values, you'd of course need to rewind that tween before you invalidate() it so that it reverts to the starting values and thus when it re-records, those remain. Otherwise it'll use the current value as the starting value (like any normal tween does). You can also record the progress value if you want, and then re-apply it after you invalidate() so that things appear more seamless mid-tween. 

Does that help?


If you still need some assistance, a minimal demo is the best next step. 


Happy tweening!

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