Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
jacksmug

Scrolltrigger, smooth scrollbar & snapping

Go to solution Solved by Cassie,

Recommended Posts

Hi everyone,

I have a question here, is there any possible way to start the snap at the end of a section (not at the start of a section)? Because as you guys can see in the codepen, it scroll the whole section until end of section. So there's no chance for the user to read the text in each section. Not sure if my code isn't implemented correctly.

What I am going to achieve is, the user still should be able to control the scroll in order for them to read the text. Here's a visual reference for you guys in the attachment, hope it helps.

Thank you!

*in this pen, I use Scrolltrigger with smooth scrollbar
 

scrolltrigger-visual-2.jpg

 

 

See the Pen XWaLGOq by syedzaquan (@syedzaquan) on CodePen

Link to comment
Share on other sites

Welcome to the forums @jacksmug

 

For custom snapping behavior, you'll can write a custom function to do that for you. You'll have to do some calculation to see if the value being passed in within those snapping areas and return the progress value is should snap to.

 

gsap.timeline({
  scrollTrigger: {
    snap: {
      snapTo(value) {
        if (value...) {
          
          return ...;
        }
        
        return value;
      }
    }
  }
})

 

 

  • Like 1
Link to comment
Share on other sites

Thank you @OSUblake, but how can I declare variable for 'value' since I am using 'smooth-scrollbar' and cannot use window offset?

Link to comment
Share on other sites

Not sure what you mean. The value is passed into the function for you and you can get the scroll position just like you did in the proxy...

bodyScrollBar.scrollTop

 

Link to comment
Share on other sites

I am sorry Blake, im a beginner in Javascript. That means 'value' represent scroll position?

I tried like this:

snapTo(value) {
  if (value > 2000) {
    bodyScrollBar.scrollTop = value;
    return value;
  }
  return value;
}

And nothing happens.

Then I tried something like this:

snapTo(value) {
  console.log(bodyScrollBar.scrollTop)
  if (bodyScrollBar.scrollTop > 1900 && bodyScrollBar.scrollTop < 2600 ) {
	bodyScrollBar.scrollTo(0, 3400, 1000);
  }
}

It make sense a little. Once I scroll between 1900 until 2600, it will go to the next section(3400) but after it snap, it jump back to the first section on the top.

Link to comment
Share on other sites

  • Solution

Hey there Jack!

 

console.log() is always your friend when you're not sure what a value is - that and the docs 👀

Value is the 'destination value' of the timeline progress. 0 would be the start of the timeline, 0.5 would be the middle and 1 would be the end.

  • Function - snap: (value) => Math.round(value / 0.2) * 0.2 feeds the natural destination value (based on velocity) into the function and uses whatever is returned as the final progress value (in this case increments of 0.2), so you can run whatever logic you want. These values should always be between 0 and 1 indicating the progress of the animation, so 0.5 would be in the middle.


To snap to a certain progress point on the timeline according to the scroll distance - you would do something like this
 

snapTo(value) {
  // log out the value and window scroll position
  console.log(value, window.scrollY);
  // if we're within the first 400px snap to halfway through the timeline otherwise continue to the natural destination point (i.e. no snap)
  if (window.scrollY < 400) {
   return 0.5;
  } else {
   return value;
  }
}


I hope this simplified demo helps you understand! The white section is the first 400px - so when it's visible we'll snap to midway through the timeline. 

 

See the Pen yLzBdXy?editors=0011 by GreenSock (@GreenSock) on CodePen

 

  • Like 3
Link to comment
Share on other sites

Hi @Cassie! Ah, now I get it. It's working! Responsive also working fine. Thanks a lot @OSUblake & @Cassie for helping me out!


So I get each scroll position manually from console.log, yeah maybe not a best way but I still able to achieve what I need.
Thank you!

snapTo(value) {
  console.log(value.toFixed(3), window.scrollY);
  if (value > 0.123 && value < 0.203) {
    return 0.232;
  } else if (value > 0.529 && value < 0.580) {
    return 0.655;
  } else if (value > 0.734 && value < 0.778) {
    return 0.915;
  } else {
    return value;
  }
}

 

  • Like 2
Link to comment
Share on other sites

Hi @Cassie, sorry it's me again. But how about when I scroll up? Is there any value that I can use to determine the scroll direction is going up/down?

So maybe I can do something like this:

if (value > 0.123 && value < 0.203 && scrollup === true)


EDIT:
Ah nevermind, i've found the solution. I added this on 'onUpdate:' to add class whenever we scroll up/down using self.direction

onUpdate: self => {
  if (self.direction === 1) {
    scroller.classList.add('scrolling-down');
    scroller.classList.remove('scrolling-up');
  } else {
    scroller.classList.add('scrolling-up');
    scroller.classList.remove('scrolling-down');
  }
  console.log("direction:", self.direction)
},


And once the class changed on scroller, I just put it in if else condition on 'snapTo'

if (value > 0.123 && value < 0.203 && scroller.classList.contains('scrolling-down'))

Thank you guys!

Link to comment
Share on other sites

You can get the direction directly from your ScrollTrigger instance...

tl.scrollTrigger.direction === 1 // down
tl.scrollTrigger.direction === -1 // up

 

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