Jump to content
Search Community

ScrollTrigger. Works, but is a bit unpredictable. Am I misusing it?

Andrei Gheorghiu test
Moderator Tag

Go to solution Solved by GreenSock,

Recommended Posts

Preamble: this is my first attempt at using ScrollTrigger.


i'm making a prototype for a friend's website, in an attempt to convince him to let me replace his 20 years old website (he's stubborn, but I'd be really happy to see his website replaced).
I wanted to also use this to spin two libs that I have been wanted to use for some time now, but haven't had the opportunity:
 - solidjs (instead of Vue / React, which I use at work)
 - ScrollTrigger, which I'm very excited about!

I've put this up in less than a day: https://github.com/andrei-gheorghiu/pwa-solid
You can view the result here: https://pwa.codemonk.digital/


The scrollTrigger animation is close to what I wanted (except that it's broken in the deployed version - it only works well on my local machine, not sure why - see 4th question)
The gallery part is slow and acts unpredictably at times (e.g: when scrolling past the last image, it keeps going one more position, sometimes). I've also noticed sometimes it acts differently when it has `markers: true` vs when they are hidden, which, again, i find quite strange.

Here are my questions:
- is there any way to configure `snap`? I'd like to snap to the nearest painting, not to the first one in the direction I'm currently scrolling.
- Another detail I'd like to change about snapping is the snapping speed. I'd like it to go to its closest picture much faster.
- I'd like to combine the separate animations in a timeline. (If this gets past the prototype phase, a lot more elements will need to be added. The idea is to make the entire website a journey. I'm thinking a timeline helps keep thing more organised and allows for easier fine adjustments later on). 
Are there any tutorials/examples on how to combine multiple separate animations into a single timeline? 

- last, but not least, the scrollTrigger seems to change its behaviour in the deployed version. When I run the app on local, using `yarn dev` or by building it and running `http-server` in the `./dist` folder, it works well, but on netlify the pinning of the image gallery is not working. Is this a known issue?

 

If you spot any mistakes I'm making ref using ScrollTrigger, please, don't spare me. I welcome any and all advice.

Thanks for looking into this.

Link to comment
Share on other sites

  • Solution
35 minutes ago, Andrei Gheorghiu said:

- is there any way to configure `snap`? I'd like to snap to the nearest painting, not to the first one in the direction I'm currently scrolling.

Sure, by default it applies directional snapping because that's almost always what people want. If they start scrolling down, it can be annoying for it to snap back upward to the current one. But you can set directional: false in the snap object to disable that - see the docs. 

 

37 minutes ago, Andrei Gheorghiu said:

- Another detail I'd like to change about snapping is the snapping speed. I'd like it to go to its closest picture much faster.

Again, check out the docs for configuring the snap. You can set a minimum and maximum duration (they can even match). Scroll down to the "snap" config property: https://greensock.com/docs/v3/Plugins/ScrollTrigger

 

38 minutes ago, Andrei Gheorghiu said:

- I'd like to combine the separate animations in a timeline. (If this gets past the prototype phase, a lot more elements will need to be added. The idea is to make the entire website a journey. I'm thinking a timeline helps keep thing more organised and allows for easier fine adjustments later on). 
Are there any tutorials/examples on how to combine multiple separate animations into a single timeline? 

There are TONS of demos about all kinds of things at https://greensock.com/st-demos

 

You'd be wise to get familiar with the position parameter - see 

 

 

I find it easiest to ignore ScrollTrigger initially and JUST get your animation working the way you want, playing directly through. THEN wire it up to the scroll position with ScrollTrigger.

 

41 minutes ago, Andrei Gheorghiu said:

The gallery part is slow and acts unpredictably at times

If you need some help with that and you think it's a GSAP-related problem, please provide a minimal demo that only focuses on that one problem, ideally with just a few colored <div> elements and no framework. The more you isolate it, the greater your chances for getting a solid solution. 

 

We just don't have time to dig through hundreds/thousands of lines of code doing a free code review for you, but we're happy to look at a minimal demo that illustrates a problem focused on GSAP (please see the forum guidelines)

 

One small thing I noticed at a glance: you're using a function-based value on a tween but you didn't set invalidateOnRefresh: true on your ScrollTrigger, so it won't re-grab that on every refresh/resize:

x: () => -(carouselRef?.scrollWidth || 0 - ww()) + "px",

 

  • Thanks 1
Link to comment
Share on other sites

Thanks for the thorough reply, Jack.
I'll follow your advice on each individual point. 
Much appreciated.

Ref: `invalidateOnRefresh: true`. Currently, whenever `ww()` (window width), `wh()` (window height) or `cw()` (carousel container width) change values, `updateScroll()` is re-run - basically starting a new animation. Could that be a performance problem?
The way I understand your advice is to define the animation only once, outside of `updateScroll()` and use `invalidateOnRefresh: true`. Is there a way for me to manually invalidate it? I want to also invalidate it when the container changes size, not only when the viewport changes size.

Link to comment
Share on other sites

4 hours ago, Andrei Gheorghiu said:

Ref: `invalidateOnRefresh: true`. Currently, whenever `ww()` (window width), `wh()` (window height) or `cw()` (carousel container width) change values, `updateScroll()` is re-run - basically starting a new animation. Could that be a performance problem?

It's tough to say without seeing a minimal demo, but you should definitely make sure you kill() the old one(s) before creating the new one so that you don't create a bunch of things that are all fighting for control of the same thing. It does sound wasteful to constantly re-create things multiple times on every resize. 

 

4 hours ago, Andrei Gheorghiu said:

The way I understand your advice is to define the animation only once, outside of `updateScroll()` and use `invalidateOnRefresh: true`. Is there a way for me to manually invalidate it? I want to also invalidate it when the container changes size, not only when the viewport changes size.

FYI, ScrollTrigger.refresh() is what recalculates all ScrollTrigger start/end positions and you can call that anytime. It's a bit expensive, though, so don't go crazy. It literally has to tear everything down, revert any changes it made (especially pinning) and then build it back up from top to bottom so that everything flows properly (things higher on the page could get pinned and push things lower down on the page, affecting their start/end positions). 

 

You can invalidate() any tween or timeline anytime. Just make sure you understand what that actually does. It flushes any recorded start/end values of the tween itself and then on the very next render, it'll parse them from wherever they're at at that time. 

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