Jump to content
Search Community

Smooth scroll to next panel - too fast

andystent test
Moderator Tag

Recommended Posts

Hey everyone,

 

This isn't directly GSAP related but I've been struggling for days to figure this out and would really appreciate some help.

 

I have built a site using GSAP and Scrollmagic.

 

The site is broken into panels and animations are triggered as you reach each panel. That part is all great and works well.

 

I also have that on the mousewheel scroll the next (or previous) panel comes into view. Almost like a snapping effect. This functionality was based on the codepen example.

 

Is there any way I can slow down the transition from one panel to the next? I have payed with the "speed" amount, but the scroll in is still really fast before that speed easing kicks in. 

 

Any ideas would be amazing! Thank you!

Andy

See the Pen gObaVQJ by andystent (@andystent) on CodePen

Link to comment
Share on other sites

Hey Andy and welcome.

 

First off, you're using jQuery's animate function which we very much do not recommend. GSAP is much more performant and allows you to do far more.

 

Secondly, calculating the offset every scroll is more performance intensive than it needs to be. I recommend using GSAP's ScrollToPlugin but you could at least only calculate the offsets on the page load and on resize. 

 

Sorry I'm not answering your question about the speed, but given I'm recommending you change your approach to use GSAP my answer would be different anyway :)

  • Like 3
Link to comment
Share on other sites

Hey @ZachSaucier Thank you for the quick reply and I appreciate the guidance.

 

Does ScrollTo work with the mousewheel scroll? 

 

I'm trying to find an example of ScrollTo plugin doing what I need. If you have come across a pen or anything that you think will point me in the right direction then please share. 

 

Thanks again, I'm going through the documentation....

Link to comment
Share on other sites

1 minute ago, andystent said:

I found this pen by Christo that seems to be what I need. I may have to ask for some guidance here though...

Good find :) Feel free to ask any questions you have.

 

Alternatively, you might be alright using CSS scroll snap points. It has pretty good support these days and you can polyfill it if necessary:

See the Pen EpPgdR?editors=0100 by newinweb (@newinweb) on CodePen

 

Then you could pair that with an intersection observer to fire off any animations that you need to fire. 

Link to comment
Share on other sites

Thanks. I'm actually testing an example using css scroll-snap. It works but the snapping speed is still pretty fast.

 

I've uploaded the actual site so maybe this will give you a better idea of what I'm trying to achieve.

Note: the scrolling is still vertical with vertically dispersed anchor points, but the actual site content is inside a fixed container. Hope that makes sense.

 

https://propertyvision.com/staging2/

Link to comment
Share on other sites

How I would approach this situation: 

  • On initialization and on resize, record the scroll positions that you want for each section. Or, if all the widths (heights, whatever) are the same, just update that value (i.e. you don't have to record all of the scroll positions since they're all the same, you can just use a counter and multiply it by the scroll amount).
  • Once the user stops scrolling, tween to the appropriate section using the scroll position and values you calculated in the last bullet (or using ScrollToPlugin based on what element is in the middle of the screen).

This approach allows you to let users skip sections if they scroll enough. If you are restricting it so that users can't skip sections, the demo you posted above from Chrysto works well.

 

Another alternative is to make dragging or keyboard clicks the primary ways of navigating (i.e. not scroll) and use Draggable's scroll type and Draggable's built in snapping functionality.

  • Like 2
Link to comment
Share on other sites

Hey Zach, Thanks for the reply. I really appreciate it!

 

After playing with Chrysto's demo I realised that his does not scroll down the page but rather just animates each slide into the container, (the container is the screen size and set to overflow:hidden). 

 

I'm trying to figure out how to adjust it so that it instead animates 100vh down/up the page (overriding the default scroll of the body and just slowly moving to the vertical position on the body). 

 

The reason is that I'm using scrollMagic to trigger the animations for each section. So when the user scrolls down and hits an ID the animations for that section play for the duration scrolling through that panel.

 

I feel like this is so close to what I need but I just don't have the knowledge yet to make it work for me.

 

I've attached a crude layout sketch that might help you understand my setup. I just want to animate down/up to the triggers.

 

Thank you!

site-layout-example.jpg

Link to comment
Share on other sites

I feel like this is what I need to change to scroll to a trigger (or down/up 100vh). 
Perhaps if the .slideContainer variable is the body? But can't figure out what the tween would be to move down to a new scroll position.

 

/*
  *   Actual transition between slides
  * */
  function goToSlide($slide)
  {
    //If the slides are not changing and there's such a slide
    if(!isAnimating && $slide.length)
    {
      //setting animating flag to true
      isAnimating = true;
      $currentSlide = $slide;

      //Sliding to current slide
      TweenLite.to($slidesContainer, 1, {scrollTo: {y: pageHeight * $currentSlide.index() }, onComplete: onSlideChangeEnd, onCompleteScope: this});


    }
  }

 

Link to comment
Share on other sites

Thank you @mikel, I really appreciate the example!

Although it doesn't quite help what I'm after it's perfect for another project I'm working on :) You've given me some excellent ideas. Thank you again!

 

The problem is that my slides that contain the animations don't actually move up/down. They are all absolutely positioned over one another to allow for overlapping of content from one slide to another as various elements animate in and out of view.

 

The animations for each slide are triggered by absolutely positioned # anchor points that are positioned at 100vh distances vertically down the  page (independent of the fixed container for the animation). So as a user scrolls down (vertically) the animation plays when they hit the relevant div that is placed 100vh apart vertically down the page. This is using ScrollMagic to trigger these. 

 

I have regular click # anchors links in the nav that scroll to each of the points, and this works perfectly. There are also arrows that can be clicked and scroll perfectly down/up to the next # anchor point, which in tern triggers the relevant animation to play in the fixed container.

 

Here's the staging link again, if it helps: https://propertyvision.com/staging2/ (note that it is currently using css scroll-snap for testing)

 

This is all perfect and I'm happy with it but all I want is that when the user scrolls the mouse wheel the body scrolls (animates) to the next # anchor point. Almost like it triggers a click # anchor link.

As I mentioned, I've experimented with css scroll-snap but it's too fast and I need more control. So if I could have a tween to that # anchor point that would be glorious! 

 

Sorry for the essay, I really hope this makes sense and that you guys can help me out. I've spent ages trying to figure this out and I just don't know how to achieve it. That's why I'm begging you guys for help :)

 

Eagerly awaiting your replies...

Thank you again!

Andy

Link to comment
Share on other sites

18 minutes ago, andystent said:

The animations for each slide are triggered by absolutely positioned # anchor points that are positioned at 100vh distances vertically down the  page (independent of the fixed container for the animation). So as a user scrolls down (vertically) the animation plays when they hit the relevant div that is placed 100vh apart vertically down the page. This is using ScrollMagic to trigger these.

Frankly, that approach doesn't make sense. If your elements are positioned fixed then you should be using a function like the one in the demo that you linked by Christo, not based on scroll position. By trying to stick with your current scroll-based approach you're making it harder on yourself and making maintainability harder.

Link to comment
Share on other sites

1 minute ago, ZachSaucier said:

Frankly, that approach doesn't make sense. If your elements are positioned fixed then you should be using a function like the one in the demo that you linked by Christo, not based on scroll position. By trying to stick with your current scroll-based approach you're making it harder on yourself and making maintainability harder.

I have no doubt that there is a better way to do this. I am just so close to the end of this long project and can't bear the thought of reworking everything again. 

Link to comment
Share on other sites

I want to thank you both again @mikel and @ZachSaucier for all the advice here. You have given me some excellent ideas and honestly if I had to start this project again I would definitely have used these approaches, and definitely will in future projects like this :)

 

In this particular case I'm very limited on time and can't afford to rework what I already have. So if you could pretty much ignore my previous, long explanations of how I've set up the site and just help me with this one thing.... 

 

I have made some modifications to a pen I found that almost does exactly what I'm after: 

See the Pen GRgjBdJ by andystent (@andystent) on CodePen

 

Working:
Scrolling up works 100% perfectly (moving to and pausing on each .slide). Yippee!

 

Not working:

- Automatically plays through each slide to the bottom on window load instead of waiting for the scroll.

- If you scroll up again and then try scrolling down it also plays through all slides to the bottom without pausing like it does when scrolling up.

 

What am I missing?! I'm so close I can feel it!

Your help here would be incredible!

 

ps: should I post this on a new thread?

Link to comment
Share on other sites

47 minutes ago, mikel said:

 

Try up and down:  triggerHook: 'onLeave'

Holy s#!+  How did I not think of that?! That works perfectly! Thank you!

 

The scrolling works perfectly now but it's causing my Nav # anchors to pause at each slide. I'm looking at potentially disabling the scrolling function when the nav links are clicked. And then re enabling it.

You wouldn't happen to know a simple way of disabling a function and then re enabling it, would you? 

 

UPDATE: 

Here is an updated Pen with the nav # anchor links included: 

See the Pen GRgjBdJ by andystent (@andystent) on CodePen

 

If you click the # links in sequential order it's fine. But if you try to skip sections it gets stuck. The smooth scrolling applied to the anchors (see bottom of js) is what's causing the issue because as you reach the trigger on the next/prev slide it stops.

Edited by andystent
Updated Pen
Link to comment
Share on other sites

To get around that with your current setup you'll have to use a variable to keep track of whether or not the nav was clicked. If it was, don't use the scrollmagic stuff. Then when the animation is complete, you change the variable back to its original value. 

 

We, of course, recommend using GSAP's ScrollToPlugin rather than scrollIntoView as it gives you more control over your animation and more useful callbacks.

  • Like 1
Link to comment
Share on other sites

Thank you Zach! I've actually change the site to use scrollToPlugin instead of that scrollIntoView. It's working perfectly on the site (strangely not on the Pen, but I'll look at that another time).

 

I've been doing some research on using a variable to track the nav click but I'm struggling a bit. Would you be able to give me a rough idea of what this would look like so I can make sure I'm even on the right track.

 

Thank you again!

 

UPDATE: I got the scrollToPlugin nav links working - I'm sure there is a better way to implement this without repeating the code... but that could be a lesson for another day...

 

See the Pen GRgjBdJ by andystent (@andystent) on CodePen

Edited by andystent
Link to comment
Share on other sites

I've tried this and the "if" works to show the "clicked" in the console. But I can't figure out how to get the not-clicked state (or false) to display "Not" in the console.

 

/// If clicked
var elementIsClicked = false;
function clickHandler(){
  elementIsClicked = true;
}

var element = document.getElementById('#slide2nav');
element.addEventListener('click', clickHandler);


function clickHandler(){
    if(element){
        console.log('Clicked'); ///works
    } else {
        console.log('Not'); ///Not working - this is where I'd want to put my scrollmagic stuff.
    }
}

 

Link to comment
Share on other sites

I've tried this and the "if" works to show the "clicked" in the console. But I can't figure out how to get the not-clicked state (or false) to display "Not" in the console the whole time that the button is not in a clicked state. I realise this is not strictly GSAP related but any guidance here would be greatly appreciated!

 

/// If clicked
var elementIsClicked = false;
function clickHandler(){
  elementIsClicked = true;
}

var element = document.getElementById('#slide2nav');
element.addEventListener('click', clickHandler);


function clickHandler(){
    if(element){
        console.log('Clicked'); ///works
    } else {
        console.log('Not'); ///Not working - this is where I'd want to put my scrollmagic stuff.
    }
}

 

Link to comment
Share on other sites

Hey Andy,

 

Not sure what you're trying to do. You have two functions that are named the same thing so one is going to override the other. Your if statement is also checking if the element exists, not if the elementIsClicked variable is true or not. Are you trying to do something like this?

 

var elementIsClicked = false;
var element = document.getElementById('#slide2nav');
element.addEventListener('click', clickHandler);

function clickHandler(){
    console.log('Clicked'); ///works
    elementIsClicked = true;
}


// inside of your listener
.on('leave', function () {
    TweenLite.to(window, .5, {scrollTo:{y:$(window).height() * (index-1), autoKill:false},ease: Linear.easeNone, onComplete: () => elementIsClicked = false})
})

I think it would be helpful for you to take some free online courses on learning JavaScript.

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