Jump to content
Search Community

Recalculate transform value for fromTo animation on screen resize

Web Bae test
Moderator Tag

Go to solution Solved by GreenSock,

Recommended Posts

Hello,

 

I am making an infinite scroll animation. It works great on initial look, and actually is hard to tell in the code pen, but gets a "jump" after resizing the window. You can probably notice it better here: https://marquee-207786.webflow.io/ which is running the same code.

 

Is there a way to recalculate the distanceToMove variable on each repeat? I tried the onRepeat function but didn't have any luck there. I also tried passing a function to the translateX parameter and returning the value there but didn't work either.

 

I threw it in to the code pen so I could post my question here but it actually works pretty well in the codepen even after resize 😭. Anyways, figured I would ask to see if anyone has any tips.

 

Thanks!

See the Pen bGMOYzG by learyjk (@learyjk) on CodePen

Link to comment
Share on other sites

Hey, 

This looks good. There is horizontal scroll I think you do not want that.
Suggestion: On window resize recalculate the DOM elements width and gaps. That changes when window shrinks or expands(this might not be the case if font size are pixels). As of now I think gap between the marquee content increase as you expand. 

 

Link to comment
Share on other sites

Thanks Trapti - Yes sorry about the horizontal scroll no worries on that it's an easy fix. The gap is set to 2rem. So I need to translate by the marquee-content width (100%) + gap distance (2rem). I converted the rem to percentage here: let gapDistPercent = (gap / marqueeWidth) * 100;

 

Now that I'm looking at it maybe I should give vw a go instead of %.

Link to comment
Share on other sites

  • Solution

For the record, you might want to check out the helper function in the docs for seamlessly looping on the horizontal axis: 

https://greensock.com/docs/v3/HelperFunctions#loop

 

But as for your demo, yeah, you could just set up a "resize" event handler, grab the .progress() of the tween at that point, save it, kill the previous tween and then recreate it based on the new values...and update the progress: 

See the Pen qBYLxbB?editors=0110 by GreenSock (@GreenSock) on CodePen

 

Does that help? 

  • Like 3
Link to comment
Share on other sites

Thank you Jack!

 

Two questions:

 

1. is the .kill() necessary? Animation seems to be working fine without it and my understanding of how you wrote the code is that we just need to set progress to zero while we recalculate then update back to the progress that we stored earlier?

2. Does it make sense to debounce the loop() function on the resize event? I'll have a play with it to see but figured I would ask you too.

 

Thanks again - really appreciate the help.

 

EDIT: I debounced it and it gives a very slight skip as the tween is recalculated but I feel like this is better than running the code without debounce ... just because. Not really sure how concerned I should be about debouncing it or not.

See the Pen xxjmBMP by learyjk (@learyjk) on CodePen

 

Edited by keeganleary
Updated for debounce
Link to comment
Share on other sites

1 hour ago, keeganleary said:

1. is the .kill() necessary? Animation seems to be working fine without it and my understanding of how you wrote the code is that we just need to set progress to zero while we recalculate then update back to the progress that we stored earlier?

Definitely. If you don't kill() that animation, it will keep running. So every time there's a resize event, it'll create a whole new infinitely-repeating tween and every one of them will be fighting for control of the same properties of the same targets. You don't notice it because basically the "last one wins". So you may have 100 animations all running and tweaking the same property, but the last one created is the last one that runs, thus the final render looks correct. You just have a bunch of unnecessary tweens doing unnecessary work. You could set overwrite: true or overwrite: "auto" if you prefer, but I think it's cleaner/faster to just kill() the old tween before you create the new one. 

 

1 hour ago, keeganleary said:

2. Does it make sense to debounce the loop() function on the resize event? I'll have a play with it to see but figured I would ask you too.

Yep. 

 

Here's a technique I use: 

// reusable function that handles setting it all up for you...
function callAfterResize(func, delay) {
	let dc = gsap.delayedCall(delay || 0.2, func).pause(),
		handler = () => dc.restart(true);
	window.addEventListener("resize", handler);
	return handler; // in case you want to window.removeEventListener() later
}

Usage: 

callAfterResize(loop);

By default, it'll wait until 0.2 seconds elapses with no "resize" events before calling the function, but you can customize it, like if you want it to wait 0.5 seconds instead: 

callAfterResize(loop, 0.5);

Done. 

 

Have fun!

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