Jump to content
Search Community

Is this doable? (Scroll Trigger)

Gonzalillo test
Moderator Tag

Go to solution Solved by GreenSock,

Recommended Posts

Good night friends, I'm new to GSAP but have been experimenting with it a little bit and found myself against an intangible wall.

What am I trying to do?

Expected behaviour: You are scrolling down, at a certain moment a scrub starts and at the bottom of the viewport a wave starts to come up. The wave settles there at the bottom, and you can see it moving up and down (like the sea would). If you keep scrolling down, the wave should scrub down again and disappear.

If you scroll up the wave scrubs up again, moves up and down, if you keep scrolling up it scrubs down.

I've been trying to do this and I got some progress but I feel like I am not doing it the correct way. For the up and down, sea style animation, I used a gsap.to() with repeat, and with the triggerActions I got it to work only when on viewport.

 

And for the first and second scrub I used gsap.fromTo(), and it worked, sort of. But... when I would scroll fast the animation would break. And that led me to realize that I am not doing this thing the right way. I may be just typing unnecesary code cause I don't know the precise mechanisms I need.

 

How would you approach something similar? The animations are (afaik):

- scrub (image arises from the bottom)

- sea like animation

- scrub (image sinks to the bottom)

This should work scrolling down and scrolling up again

 

(THE CODEPEN ONLY HAS THE 2 SCRUBS, IN THE CODEPEN THEY WORK FINE BECAUSE IT ISNT AN IMAGE, AND THE SCROLL IS TOO SHORT, BUT ON A NORMAL HEIGHT SCREEN IT GLITCHES. IS THIS THE MOST PERFORMANT WAY TO DO WHAT I AM TRYING TO DO?)
 

See the Pen vYVGaWx by zalogon23 (@zalogon23) on CodePen

Link to comment
Share on other sites

On 4/16/2023 at 5:30 PM, GreenSock said:

I'm not entirely sure what you're looking for, but it sounds to me like the best approach is to use a container for the enter/exit, and then just have a looping animation on the wave element itself that you can play()/pause(): 

 

 

 

Does that help? 

Yeah, it works. But it is pretty similar to my example. The problem I had was when setting scrub to a number (1,2,3) if I were to scroll fast to the bottom of the page the wave would pop up aoas (when at the bottom of the screen it was supposed to hide again)

Link to comment
Share on other sites

  • Solution
1 hour ago, Gonzalillo said:

Yeah, it works. But it is pretty similar to my example. The problem I had was when setting scrub to a number (1,2,3) if I were to scroll fast to the bottom of the page the wave would pop up aoas (when at the bottom of the screen it was supposed to hide again)

Yes, that makes logical sense. That's exactly what should happen. A numeric scrub value just means it takes that many seconds for the playhead to "catch up". So let's say the ScrollTrigger at the top has scrub: 2 on an animation that makes the element move 80px and then you scroll really fast. So let's say the element has only moved 5px at this point (because it takes 2 full seconds to travel to where it's supposed to be) but you've got ANOTHER ScrollTriggered animation that suddenly forces that element to 80px and animates back to 0. See the issue? And now you've got TWO animations fighting with each other for control of the same element. No bueno. 

 

So it's just a logic issue in the way you're setting things up. 

 

One way to solve this is to put the enter and exit animations both into a timeline, and add the ScrollTrigger to the timeline instead. And then put a bunch of blank space in the middle of the timeline so that the enter/exit just happen on the two extreme ends. You can tweak the amount of empty space to control the proportions. I used a tween on each end with durations of 1 second each, and then put 8 seconds in the middle so that each end is roughly 10% of the space. 

 

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

 

Notice that works great with scrub: 2, for example.

 

Better? 

Link to comment
Share on other sites

1 hour ago, GreenSock said:

Yes, that makes logical sense. That's exactly what should happen. A numeric scrub value just means it takes that many seconds for the playhead to "catch up". So let's say the ScrollTrigger at the top has scrub: 2 on an animation that makes the element move 80px and then you scroll really fast. So let's say the element has only moved 5px at this point (because it takes 2 full seconds to travel to where it's supposed to be) but you've got ANOTHER ScrollTriggered animation that suddenly forces that element to 80px and animates back to 0. See the issue? And now you've got TWO animations fighting with each other for control of the same element. No bueno. 

 

So it's just a logic issue in the way you're setting things up. 

 

One way to solve this is to put the enter and exit animations both into a timeline, and add the ScrollTrigger to the timeline instead. And then put a bunch of blank space in the middle of the timeline so that the enter/exit just happen on the two extreme ends. You can tweak the amount of empty space to control the proportions. I used a tween on each end with durations of 1 second each, and then put 8 seconds in the middle so that each end is roughly 10% of the space. 

 

 

 

 

Notice that works great with scrub: 2, for example.

 

Better? 

jesus christ spray me with your holy blood! that's exactly what I was trying to achieve man! So you managed to do this by setting the scrollTrigger to the timeline instead of setting it on the individual tweens. When you use duration inside of a scrubbed context the duration now refers to units of physical distance? That would be the reason for the 1, 1, 8 durations behaving as 10%, 10%, 80% scroll distance?

I can not stress how helpful you've been. I didn't know people were that active here. Quite cool

Link to comment
Share on other sites

1 hour ago, GreenSock said:

Yes, that makes logical sense. That's exactly what should happen. A numeric scrub value just means it takes that many seconds for the playhead to "catch up". So let's say the ScrollTrigger at the top has scrub: 2 on an animation that makes the element move 80px and then you scroll really fast. So let's say the element has only moved 5px at this point (because it takes 2 full seconds to travel to where it's supposed to be) but you've got ANOTHER ScrollTriggered animation that suddenly forces that element to 80px and animates back to 0. See the issue? And now you've got TWO animations fighting with each other for control of the same element. No bueno. 

 

So it's just a logic issue in the way you're setting things up. 

 

One way to solve this is to put the enter and exit animations both into a timeline, and add the ScrollTrigger to the timeline instead. And then put a bunch of blank space in the middle of the timeline so that the enter/exit just happen on the two extreme ends. You can tweak the amount of empty space to control the proportions. I used a tween on each end with durations of 1 second each, and then put 8 seconds in the middle so that each end is roughly 10% of the space. 

 

 

 

 

Notice that works great with scrub: 2, for example.

 

Better? 

One last thing though. Do you how to avoid the wave flickering for a ms at the beginning? When it first renders you can see it at y:0 and then disapperas

Link to comment
Share on other sites

See the Pen zYmBmOz by zalogon23 (@zalogon23) on CodePen

Cool, so the flickering thing got solved by setting the default css to a position where you cannot see the wave on screen.

And for some reason I dont like too much to see the "+=8" string, so I used the delay property instead and it worked the same. 
But the core mechanism is  still the one you proposed

Link to comment
Share on other sites

3 hours ago, Gonzalillo said:

Cool, so the flickering thing got solved by setting the default css to a position where you cannot see the wave on screen.

Yep, that's just because the page gets rendered initially, THEN the browser executes JavaScript. So you found the correct solution - set the CSS to hide the element and then use gsap to show/animate it.

 

3 hours ago, Gonzalillo said:

And for some reason I dont like too much to see the "+=8" string, so I used the delay property instead and it worked the same. 

How dare you insult the uber-flexible position parameter🙃 That's fine if you prefer a delay like that. The position parameter can do a whole lot more than a delay can, but in this case all you're really doing is a delay anyway so that's fine. Whatever you find most intuitive. 

 

4 hours ago, Gonzalillo said:

When you use duration inside of a scrubbed context the duration now refers to units of physical distance? That would be the reason for the 1, 1, 8 durations behaving as 10%, 10%, 80% scroll distance?

Well I wouldn't necessarily call them units of physical distance per se, but it sounds like you've got the overall concept correct, yes. They are indeed ratios that relate to the scroll distance. 

 

4 hours ago, Gonzalillo said:

I can not stress how helpful you've been. I didn't know people were that active here. Quite cool

🥳 Very glad it helped. And yes, we spend a crazy amount of time tending to these forums, and we've been doing so for over a decade. It's the primary way we support our users and cultivate community. We want people to feel like GSAP isn't "just" a library like other open source ones. We do things very differently. We stand behind the tools with ongoing support and we do our best to serve folks around here even though the vast majority of them never pay us a dime. It's Club GreenSock members that make everything we do possible. 👍

 

Anyway, good luck with the project and I hope to see you around the forums. It's one of the best ways to learn the tools - try helping other people around here and your skills will grow surprisingly quickly. 

Link to comment
Share on other sites

On 4/17/2023 at 3:30 AM, GreenSock said:

I'm not entirely sure what you're looking for, but it sounds to me like the best approach is to use a container for the enter/exit, and then just have a looping animation on the wave element itself that you can play()/pause(): 

 

 

Thank you for your help. That was also a problem that I need a method to solve.

Does that help? 

 

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...