Jump to content
Search Community

Use new Observer plugin within a pinned Scrolltrigger

ryjohnson test
Moderator Tag

Recommended Posts

I'm looking to create a pinned section that will animate similar to this new demo vs scrubbing a timeline (need to ensure animations are complete before allowing the user to scroll to the next section). Is there a way to place something like this within a ScrollTrigger pinned section, then unpin it once it gets to the last slide?

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

  • Like 1
Link to comment
Share on other sites

If I understand correctly, that would be logically impossible because pinning is totally dependent on the scrollbar position (it's not an on-demand thing where you say "hey, pin...and now unpin"). It's sorta like you're asking to have something be both dependent on the scrollbar position and not be dependent on it at all. You could, however, just make your container element position: fixed and then within that, do whatever you want whenever you want but that obviously wouldn't allow for natural scrolling on the rest of the page. 

 

You could also have normal pinning and then when that section gets pinned, you use Observer to basically hijack any wheel/touch events so that the user can't really scroll further until your conditions are met. 

 

Good luck!

  • Like 1
Link to comment
Share on other sites

Thanks! That approach sounds perfect. I'm able to get the Observer to initiate on pin, but I don't see anything in the docs about programmatically disabling the Observer and unpinning the ScrollTrigger once the animation is complete. Is there something I might be missing, or an example you could point me towards?

Link to comment
Share on other sites

6 hours ago, ryjohnson said:

I'm able to get the Observer to initiate on pin, but I don't see anything in the docs about programmatically disabling the Observer and unpinning the ScrollTrigger once the animation is complete. Is there something I might be missing, or an example you could point me towards?

 

Both plugins have disable/enable methods, but you really can't programmatically unpin a ScrollTrigger. It unpins when it's reached it's end bar position according to the actual scroll position.

 

I tried making a simple demo using Jack's second idea, and it does not work well in browsers that have a smooth scrolling effect, like Edge on Windows. It was possible to blow partially past the pinning if you scroll fast, so it may not possible using that technique without a lot of work. 

 

I would definitely try Jack's first suggestion of just using a container that is fixed.

 

Link to comment
Share on other sites

  • 1 year later...
On 4/22/2022 at 3:52 PM, ryjohnson said:

Thanks! That approach sounds perfect. I'm able to get the Observer to initiate on pin, but I don't see anything in the docs about programmatically disabling the Observer and unpinning the ScrollTrigger once the animation is complete. Is there something I might be missing, or an example you could point me towards?

Hi, so I've had this need as well and this is how I went about it:

 

First, I created the observer using ScrollTrigger.observe({...}). Then immediately after, I disabled the observer, with observer.disable()

 

Then I created a ScrollTrigger instance with start and end and pin set to true.

Then onEnter and onEnterBack I enable the observer.

 

The observer has preventDefault set to true, so, when it's enabled, normal scrolling is disabled.

Then I have a condition for disabling the observer when the animation is done.

 

I've pasted the necessary segments of the code here with comments in-between. I hope it helps.

 

      const animateOnScroll = (direction: -1 | 1) => () => {
        if (state.current.isAnimating) return
 
        let nextIndex = state.current.productIndex + direction

 

        if (nextIndex < Min || nextIndex > Max) {
          state.current.observer?.disable() // comment: this is where I disable the observer so user can resume normal scroll of the page, because if this condition meets, animation is done.
          return
        }
 
        state.current.isAnimating = true
        replayAnimation(wrap(nextIndex))
      }
 
const observer = ScrollTrigger.observe({
        target: ref.current,
        type: "wheel,touch,scroll",
        wheelSpeed: -1,
        tolerance: 10,
        preventDefault: true, // set to true, to disable normal scroll,
        onUp: animateOnScroll(1),
        onDown: animateOnScroll(-1),
 })
 
      observer.disable()
      state.current.observer = observer
 
      ScrollTrigger.create({
        trigger: ref.current,
        start: () => "top " + getTop() + "px",
        end: "+=100px",
        scrub: 1,
        pin: true, // set to true so that scroll trigger pins the section while animation is on
        markers: false,
        animation: gsap.timeline().to(ref.current, { opacity: 1 }),
        toggleActions: "play none none reverse",
        onEnter: () => observer.enable(),
        onEnterBack: () => observer.enable(),
      })

 

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