Jump to content
Search Community

ScrollTrigger snap just if is close to label (something like css scroll-snap-type proximity)

Hermes Grau test
Moderator Tag

Recommended Posts

Hi!

 

I am looking for a way to prevent the snap to labels functionality of ScrollTrigger if it is not close enough to any label (like an amount of pixels, or a function to build a logic to prevent snapping).

The result I am looking for should be similar to the css property scroll-snap-type: proximity.

 

Is it possible?

Thanks!

  • Like 1
Link to comment
Share on other sites

Thank you Jack!
I didn't notice that.

 

So, I've tested it and for now my solution could be:

snap: (value) => {
  const snapPoints = [0, 0.5, 1];
  const proximity = 0.1;

  for (let i = 0; i < snapPoints.length; i++) {
    if (value > snapPoints[i] - proximity && value < snapPoints[i] + proximity) {
      return snapPoints[i];
    }
  }
}

Now I just need to find the way to calculate the snap points dynamically from the sections/labels positions.

 

Working codepen:

See the Pen xxWQNWM by hermesgrau (@hermesgrau) on CodePen

 

Anyway, as Cassie said, could be great to have this as a built in option.
For whole page sections I feel more natural to let the user stop whenever he/she wants, and fix the position just on the edges.

 

Thank u both!

 

  • Like 2
Link to comment
Share on other sites

Thank you Cassie!

This is much better

 

I've improved a little bit the example, because labels was being added to the end of the sections. If a section is taller than the window, it didn't snap to the start of the section, just to the end.

 

Here is the result with a larger section

See the Pen qBoLWeW by hermesgrau (@hermesgrau) on CodePen

  • Like 1
Link to comment
Share on other sites

  • 10 months later...

Hi!

Sure, I've added a nav.

See the Pen qBoLWeW by hermesgrau (@hermesgrau) on CodePen

 

I have used ScrollTo plugin and a helper function to scroll to a timeline label.

function labelToScroll(timeline, label) {
  let st = timeline.scrollTrigger;
  return st.start + (st.end - st.start) * (timeline.labels[label] / timeline.duration());
}

 

Helper function found here: 

 

Then you can do something like this:

gsap.to(window, {
  duration: .6,
  scrollTo: labelToScroll(tl, 'your-label'),
})

 

You could add a data-scroll-to to the nav links with the label you want to target.

 

  • Like 4
Link to comment
Share on other sites

very nice code, you rock, thanks indeed!

One last question: could we launch a method when next section is half in view (going up or down) ?

Let's imagine some section need the nav to be white, cause their background is dark, and others need black nav because of clear backgounds ?

Or imagine that when a section is half in view, we want to launch an animation inside that section ?

Link to comment
Share on other sites

hey @mvaneijgen, thanks for your answer. Yes I made some tests, and could detect it with a scroll event on the window scanning for sections positions, but I was wondering if GSAP would be able to tell me more efficiently when this happens (a little like waypoints would).
This system was just a possible option but the client finally chose to go Fullpage.js... and as I have to end this project before Thursday (cause then I'll be on holiday :) ), I won't be able to make an example or tests right now. So that was just a question in order to have an idea for next time.

In real life you're absolutely right I would have made deeper testings before asking.

Thanks anyway

Link to comment
Share on other sites

Hi @steph72. The thing is that the whole sections movement is just an animation (a timeline). The page is forced to have a height just to provoke the scroll necessary to connect this timeline animation to the page scroll, but the sections are not really scrolling. From there, I'm afraid that any function or animation related to the section's positions should be called inside this timeline at the point that you need.

You could even create different timelines for the inner sections animations, and add() to the main timeline at the right position.

Does it help?

Link to comment
Share on other sites

Thanks @Hermes Grau. I stopped my tests at this point which was working (but not cleaned nor finished). My main fear was mainly about performance, but this was working. Unfortunately, I won't go further for the moment at least, but it was a nice test.

window.addEventListener('scroll', () => {
   const sections = document.querySelectorAll('section')
   const btn = document.querySelector('.btn-menu')
   sections.forEach((section) => {
      const rect = section.getBoundingClientRect()
      if (rect.top < window.innerHeight / 2 && rect.bottom > 0) {
         if (section.classList.contains('white-menu')) {
            btn.classList.add('white')
         } else {
            btn.classList.remove('white')
         }
      }
   })
})
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...