Jump to content
Search Community

ScrollTrigger start property and using functions

acg test
Moderator Tag

Recommended Posts

I'm trying to find a way to trigger something based on an element which is "dynamically" located/sized. So, I can't simply set the "start" parameter to a more traditional "top top" or even "top top+=100" because the "100" value may change.

 

So, I believe the best option would be to set the "start" property to a function where I could dynamically calculate that number. However, the GSAP docs are a bit unclear with this feature (or perhaps I'm just missing it). If I set "start" to a function, are there any parameters? Ideally it would be the ScrollTrigger object (or a way of determining it) so the function could return values based on other options configured in the ScrollTrigger (like the "id").

 

Or am I missing some other strategy that would better? Any help would be appreciated!

 

Link to comment
Share on other sites

It's important to understand how ScrollTrigger handles the positioning stuff...

 

Since scrolling is VERY performance-sensitive, we put a lot of effort into optimizing ScrollTrigger. It calculates the intersection point with the viewport UP FRONT (when ScrollTrigger.refresh() is called and that happens automatically when the page loads or gets resized). It figures out the start and end number and then when you scroll, all it has to do is check "is the new scroll position between the start and end? If not, ignore it. If so, update the ScrollTrigger". 

 

If, however, we tried to dynamically check every trigger element on every scroll event by doing something like .getClientBoundingRect() ("are you in the viewport yet?"), that'd be terrible for performance but it'd accommodate your scenario quite well (dynamic stuff). 

 

In 99.9% of cases, the trigger element isn't shifting all over the place dynamically while scrolling, so this strategy is fantastic - highly performant. 

 

If you really need to move your trigger element all over the place like on every tick or something, then you could just leverage the ScrollTrigger.isInViewport() in a scroll event handler or requestAnimationFrame and then fire of whatever you need at that point. It's not a good fit for a standard ScrollTrigger.

 

That being said, if you're just dynamically placing an element after the initial load and you want it to calculate its start/end position after you place it (assuming it's not continuing to move around), you could call ScrollTrigger.refresh() to have everything recalculate (necessary if some ScrollTriggers are affected by others, like pinning) or just call .refresh() on the individual one you're creating which is much faster: 

let tween = gsap.to("#id" {scrollTrigger: {start: "top center"...}});

// later you might reposition it(?)
gsap.set("#id", {y: 100});

// so refresh the ScrollTrigger 
tween.scrollTrigger.refresh();

// if the tween already started and the repositioning would affect any of the tweening values, you may need to tween.invalidate() as well, but it's unlikely.

I hope that helps. If you still need assistance, please provide a minimal demo

Link to comment
Share on other sites

Jack, thanks for the detailed background.

But do you have any additional info on the parameters if "start" is used as a callback?

 

The issue I'm trying to solve is something like a "sticky header bar" whose size dynamically changes based on the width of the browser because of "word wrap". At larger widths, the header height is small. At narrower widths, text wraps, and the header is larger. So, if we want to trigger when an element goes under the sticky header (which *visually* appears like a "leave" even though it obviously doesn't leave the viewport), we need to dynamically adjust the "end".

Link to comment
Share on other sites

7 minutes ago, acg said:

But do you have any additional info on the parameters if "start" is used as a callback?

 

A function-based start/end value will only be called when a .refresh() happens on that ScrollTrigger. 

 

So, for example, you could put a console.log() inside there and see that it'll fire a couple of times on load (because a ScrollTrigger.refresh() happens automatically on DOMContentLoaded and when the window.onload fires) and then also when you resize the viewport. Of course you can call .refresh() whenever you want. Just beware that ScrollTrigger.refresh() can be expensive because it has to tear down any pinning, etc. to return things to their natural flow to do proper measurements and then build it back top-to-bottom to ensure the triggers lower on the page are properly affected by any pinning that occurs higher up. 

 

So yeah, you could probably do something like: 

start: () => "top " + header.offsetHeight + "px"

 

Does that clear things up? 

Link to comment
Share on other sites

Helpful, but I don't think the main focus of my question has question has been addressed: Do the start/end functions include any parameters?

 

For example, suppose I want to do something different based on the id of element involved. Ideally, something like:

 

start: (st) => "top " + $("#"+st.vars.id).height() + "px"

Thanks again. I really appreciate your 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...