Jump to content
Search Community

Scrolltrigger struggles: 2 X scrolltriggers back to back

newguy123 test
Moderator Tag

Recommended Posts

Hi Guys

 

I have 1 X Scrolltrigger, ie the Apple Airpods example, with 4 titles appearing over it as you scroll. This works great, as expected.

 

However, immediatly AFTER the 1st scrolltrigger finishes, I want the next one to start as it come in to view. Its a video and it should loop and only start playing when it comes into view. What's more, I want the video to STAY PINNED for a bit, enough for the next 2 titles "AAA" and "BBB" to scroll past. Then the video should unpin scroll out of view while the next section "THE END" scrolls into view.

 

I have 2 troubles here. I can't seem to pin the video and I cant seem to play it when it comes into view, while the 2 titles scrolls over while the video is pinned.

 

 

See the Pen NWmReyM by newguy123 (@newguy123) on CodePen

Link to comment
Share on other sites

Take a look at your start and end triggers. Instead of video.play() and .pause(), console.log('onEnter has fired') and check the console if what you think should happen is happening.

 

For the stacking of element and then animating check my post of creating a stacking card effect, but in stead of cards you have a video and two pieces (or three) of text. 

 

Hope it helps and happy tweening! 

 

  • Like 1
Link to comment
Share on other sites

11 minutes ago, mvaneijgen said:

Take a look at your start and end triggers. Instead of video.play() and .pause(), console.log('onEnter has fired') and check the console if what you think should happen is happening.

 

For the stacking of element and then animating check my post of creating a stacking card effect, but in stead of cards you have a video and two pieces (or three) of text. 

 

Hope it helps and happy tweening! 

 

To be honest I dont know what is going on here.
For example, if I simply change the scrolltrigger code from a timeline like so:

var tl1main = gsap.timeline({
    scrollTrigger: {
      trigger: "video",
      start: "top bottom",
      end: `+="200vh"`,
      markers: true,
      pin: "#video",
      onEnter: () => video.play(),
      onLeave: () => video.pause(),
      onLeaveBack: () => video.pause(),
      onEnterBack: () => video.play(),
    }
});

and change that to:
 

ScrollTrigger.create({
    trigger: "video",
    start: "top bottom",
    end: "bottom top",
    markers: true,
    pin: "#video",
    onEnter: () => video.play(),
    onLeave: () => video.pause(),
    onLeaveBack: () => video.pause(),
    onEnterBack: () => video.play(),
});

then the video playes fine, however for some odd reason the video is only 1 pixel in height then, and its still not pinned

Link to comment
Share on other sites

36 minutes ago, newguy123 said:

To be honest I dont know what is going on here.


There's acctually a couple of things problematic with your example.
 

  1.  You've got transforms apllied to the video element (which you use as the trigger and want to pin) and also to its parent element;
    they are likely going to mess with ScrollTrigger in some way - so unless you know exactly what you're doing I'd first go without them.
     
  2. Your video and its parent have a lower z-index set than the subsequent containers.
    So even if things would work right for you with regard to ScrollTrigger, the video would still sit on top of the subsequent containers which thus you would not get to see then until the video got unpinned.
     
  3. You are using an invalid value for your end. With ScrollTrigger a window's height is represented in % and not in vh.
    vh units are not valid with ScrollTrigger if I'm not totally mistaken.
     
  4. your start: "top bottom"doesn't make much sense for a pinning ScrollTrigger.
    If pinning something when its top hits the bottom of the viewport you will never see it getting pinned, as it is not in viewport that whole time then.
    If you want to trigger the video to start playing earlier, while pinning it at some different point, you'll probably have to use two different ScrollTriggers.
     
  5. As video elements can be a bit tricky to handle to some degree, I would suggest not pinning the video element itself but its wrapping container instead.
    Just set pinSpacing to false and you'll get the same effect you're after.

     

All those things changed, you should already see something working a lot better.

See the Pen QWPKoPM by akapowl (@akapowl) on CodePen

  • Like 3
Link to comment
Share on other sites

Awesome thanks @akapowl

 

For the video, as per your suggestion, I added the 2nd scrolltrigger for the video to make it play automatically at a different time, than what its container reaches the top of the viewport. This works great.

 

I like the way AAA and BBB scrolls past, over the video in usual fasion, so that part is great also.

 

The next bit of my troubles, are that I want the entire video (ie both scrolltriggers for the bunny video), to come in slightly earlier in the scroll. Currently the Airpods scroll completes, and after it is done, it scrolls out of view and the video scroll in. It would be great, if I can have the video coming in already, at the part where the Airpod's title "4444444" starts fading out. I can't figure out how to do this and seems the video will always only come in AFTER the Airpods scroll fully completes.

 

Also, I adjusted the video scroll some more, to also fade in and fade out. The problem with this part is that my initial fade in, seems to take too long. No matter what I set the duration to, it doesnt seem to make a difference.
For the fading out part, same thing, it takes too long to fade out. Also, it start to fade out too soon. I only want it to start fading out when "BBB" is almost out of view, but before "The End" comes in.

 

See the Pen dyLpxqp by newguy123 (@newguy123) on CodePen

 

 

Link to comment
Share on other sites

4 hours ago, newguy123 said:

The next bit of my troubles, are that I want the entire video (ie both scrolltriggers for the bunny video), to come in slightly earlier in the scroll.


Then logically you'll need to make sure that your video is appearing on the page further up than it is now.

You could e.g. calculate the distance it takes to scroll from when the 4s start fading out in your one ScrollTriggger until the point where your video enters the viewport now and then you'd know by how much you'd have to offset your video to the top for it to enter the viewport when the 4s start fading out. And this you'd have to of course do before you set up your ScrollTriggers for the video.

Or - since your airpods Scrolltrigger is dependent on the window height anyway - just set a vh value that fits for you via CSS, e.g. via a negative margin-top on your video container. That is what I did in the codepen below. A bit of a warning though; keep in mind that since you have a numerical scrub on your airpods scrollTrigger, the scroll of the video and the fading out of the 4s will never be truly 'synced' - which will become more apparent when you scroll fast.

 

 

4 hours ago, newguy123 said:

Also, I adjusted the video scroll some more, to also fade in and fade out. The problem with this part is that my initial fade in, seems to take too long. No matter what I set the duration to, it doesnt seem to make a difference.


You are adding the tweens for the fading of the video to your first timeline - which has a scrub set.
I'm not sure if that is what you want to begin with, since you added the tweens at the very bottom of your JS after you created all the ScrollTriggers.

And if you add it to the pinning Scrolltrigger like you do, of course it will only start fading in the opacity once the video has reached the top, and then the 'over-scrolling' you were trying to achieve wouldn't make any sense at all anymore.

So you'll probably want to add the tweens to that other, non-pinning, ScrollTrigger instead and also set it to scrub.

That out of the way, here's something from the article on the most common ScrollTrigger mistakes:
 

Quote


HOW TO MAKE "SCRUB" ANIMATIONS TAKE LONGER
 

The duration of a "scrub" animation will always be forced to fit exactly between the start and end of the ScrollTrigger position, so increasing the duration value won't do anything if the start and end of the ScrollTrigger stay the same. To make the animation longer, just push the end value down further. For example, instead of end: "+=300", make it "+=600" and the animation will take twice as long.
 

If you want to add blank space between parts of a scrubbed animation, just use empty tweens as the docs cover.
 


https://gsap.com/resources/st-mistakes/#how-to-make-scrub-animations-take-longer

------

BTW - @GreenSock @Rodrigo @Cassie - there's a wrong link in that blue information box in that section of the article.

It is an old URL which previously pointed to this content:
https://gsap.com/docs/v3/Plugins/ScrollTrigger/#how-does-duration-work-with-scrub-true

But although the general concept of how durations work with scrubbed: true is explained there, there isn't any mention of empty tweens as suggested in that blue information box - sort of confusing altogether.

Edit:
I also found a typo in the docs for the position parameter with regard to percentages, that I'm mentioning further down the post. Reporting it here, where it might be better to catch.
 

Quote


https://gsap.com/resources/position-parameter/

A complex string based on a percentage. When immediately following a "+=" or "-=" prefix, the percentage is based on total duration of the animation being inserted. When immediately following "&lt" or ">"

... looks like the less-sign didn't get processed correctly; it says "&lt" instead of "<" in the docs.
 


-----

That second link explains how durations work with scrub: true, @newguy123  - you should have a thorough read on it to understand the concept.

I added some comments in the codepen below that might help better understand it in combination with what the docs say.

In that codepen I also make use of the aforementioned empty tween to create a 'gap' where nothing happens between the fading in and fading out.

So I also got rid of your approach with the position parameter - of course you can do it with the position parameter, too, but you'd have to use the proper value - and for understanding how durations work with scrub: true to begin with it might be easier to work with empty tweens at first.

Also, I'm pretty sure the value you use for the position parameter (i.e. "99%") again is invalid.

Here's what the docs say with regard to percentage values in the position parameter. You see, a percentage value without any prefix is not listed in there. In your example you could in fact change it to "0%" and it would still behave exactly the same as it does now.
 

Quote
  • A complex string based on a percentage. When immediately following a "+=" or "-=" prefix, the percentage is based on total duration of the animation being inserted. When immediately following "&lt" or ">", it's based on the total duration of the previous animation. Note: total duration includes repeats/yoyos. Examples:

    • "-=25%" - overlap with the end of the timeline by 25% of the inserting animation's total duration
    • "+=50%" - beyond the end of the timeline by 50% of the inserting animation's total duration, creating a gap
    • "<25%" - 25% into the previous animation (from its start). Same as ">-75%" which is negative 75% from the end of the previous animation.
    • "<+=25%" - 25% of the inserting animation's total duration past the start of the previous animation. Different than "<25%" whose percentage is based on the previous animation's total duration whereas anything immediately following "+=" or "-=" is based on the inserting animation's total duration.
    • "myLabel+=30%" - 30% of the inserting animation's total duration past the label "myLabel".


https://gsap.com/resources/position-parameter/

That all said, here's the codepen.


See the Pen ExJNxJO by akapowl (@akapowl) on CodePen

  • Like 3
Link to comment
Share on other sites

58 minutes ago, akapowl said:


Then logically you'll need to make sure that your video is appearing on the page further up than it is now.

You could e.g. calculate the distance it takes to scroll from when the 4s start fading out in your one ScrollTriggger until the point where your video enters the viewport now and then you'd know by how much you'd have to offset your video to the top for it to enter the viewport when the 4s start fading out. And this you'd have to of course do before you set up your ScrollTriggers for the video.

Or - since your airpods Scrolltrigger is dependent on the window height anyway - just set a vh value that fits for you via CSS, e.g. via a negative margin-top on your video container. That is what I did in the codepen below. A bit of a warning though; keep in mind that since you have a numerical scrub on your airpods scrollTrigger, the scroll of the video and the fading out of the 4s will never be truly 'synced' - which will become more apparent when you scroll fast.

 

 


You are adding the tweens for the fading of the video to your first timeline - which has a scrub set.
I'm not sure if that is what you want to begin with, since you added the tweens at the very bottom of your JS after you created all the ScrollTriggers.

And if you add it to the pinning Scrolltrigger like you do, of course it will only start fading in the opacity once the video has reached the top, and then the 'over-scrolling' you were trying to achieve wouldn't make any sense at all anymore.

So you'll probably want to add the tweens to that other, non-pinning, ScrollTrigger instead and also set it to scrub.

That out of the way, here's something from the article on the most common ScrollTrigger mistakes:
 


https://gsap.com/resources/st-mistakes/#how-to-make-scrub-animations-take-longer

------

BTW - @GreenSock @Rodrigo @Cassie - there's a wrong link in that blue information box in that section of the article.

It is an old URL which previously pointed to this content:
https://gsap.com/docs/v3/Plugins/ScrollTrigger/#how-does-duration-work-with-scrub-true

But although the general concept of how durations work with scrubbed: true is explained there, there isn't any mention of empty tweens as suggested in that blue information box - sort of confusing altogether.

Edit:
I also found a typo in the docs for the position parameter with regard to percentages, that I'm mentioning further down the post. Reporting it here, where it might be better to catch.
 


-----

That second link explains how durations work with scrub: true, @newguy123  - you should have a thorough read on it to understand the concept.

I added some comments in the codepen below that might help better understand it in combination with what the docs say.

In that codepen I also make use of the aforementioned empty tween to create a 'gap' where nothing happens between the fading in and fading out.

So I also got rid of your approach with the position parameter - of course you can do it with the position parameter, too, but you'd have to use the proper value - and for understanding how durations work with scrub: true to begin with it might be easier to work with empty tweens at first.

Also, I'm pretty sure the value you use for the position parameter (i.e. "99%") again is invalid.

Here's what the docs say with regard to percentage values in the position parameter. You see, a percentage value without any prefix is not listed in there. In your example you could in fact change it to "0%" and it would still behave exactly the same as it does now.
 


https://gsap.com/resources/position-parameter/

That all said, here's the codepen.

 

 

Thank you, this information is absolutely golden!!!

 

Most of what you say makes sense, and I've adjusted the last timeline for the fading duration to be 0.5, 3, 0.5 respectively and that makes it fade in and out faster, while having the full blank tween visible longer, which is great.

 

Now only 2 things I dont fully understand, and that is:

1)

the bit you mention that when scrolling fast, things might not always be in sync between where the video is suppose to start. Is that mainly because we are dealing with more than 1 scrolltrigger, or why? Any way to lock it in place so no matter if you scroll fast or slow, it appears where it should?

2)

You're adding id's into each of the video's scrolltriggers. Does that do anything, or its mainly for us as devs to keep track of which scrolltrigger does what?

Link to comment
Share on other sites

7 minutes ago, newguy123 said:

the bit you mention that when scrolling fast, things might not always be in sync between where the video is suppose to start.
Is that mainly because we are dealing with more than 1 scrolltrigger, or why?


https://gsap.com/docs/v3/Plugins/ScrollTrigger/

 

Quote

scrub: 1, // smooth scrubbing, takes 1 second to "catch up" to the scrollbar


It's because one of those is a tween on a ScrollTrigger with scrub: 1 - so it will take 1 second to catch up to the scroll position - and the other one is natively scrolling. So there will always be a discrepancy between the two - which will only become more apparent the faster you scroll.


If you want both to behave the 'exact same', set scrub: true instead of scrub: 1 to your airpods ScrollTrigger. 
You'll lose the smoothness of the scrub then, of course.

Or instead tween the 'over-scrolling' of the video via a ScrollTrigger that also has a numeric scrub of 1 set.
But then, one way or another, you'll get a discrepancy again between that video container and the subsequent containers which would scroll natively.

At this point you might end up in a 'tween everything' approach like Mitchel (@mvaneijgen) suggested in his earlier answer with the thread he linked to.

An alternative to that approach could be to use overall smooth-scrolling instead, e.g. via ScrollSmoother alongside scrub: true on the airpods ScrollTrigger.
Technically it's also a 'tween everything' approach - just on another level. And you'll lose some native browser features like e.g. jump-to search via F3.

Is it worth the extra mile? Depends on how much you're a sucker for detail and how much the - most of the time visually small - asynchrony bothers you.


Is any one better than the other? Depends on you again. Each of them has its downsides, if you ask me.

Personally I'd go with the overall smooth-srolling - but that is merely a suggestion, not a recommendation by any means.
It will definitely add another level of complexity with some regards.
 

26 minutes ago, newguy123 said:

You're adding id's into each of the video's scrolltriggers.
Does that do anything, or its mainly for us as devs to keep track of which scrolltrigger does what?


The latter - here it was just to keep track of what marker is related to which ScrollTrigger.

But it can also be a helpful tool if at any point in time you might need to target any specific ScrollTrigger on your page for whatever reason logic-releated.
 

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