0

I am trying to create a simple, "one-page" scroll.

the goal is to scroll window.innerHeight on scroll - just like fullPage.js and simillar libraries do.

  • lastScrollTop is for determining the direction of scroll.
  • wh is for adding and subtracting the window.innerHeight from the current ScrollTop.

The problem is, that once you scroll (once), it scrolls to the very bottom. My attempt to solve this was to create var A, which is turned to 1 when the scroll animation is going, doesn't seem to be working.

var lastScrollTop = 0;
    var a = 0;
   var wh = 0; 

    $(window).scroll(function () {
        
        var st = $(window).scrollTop();
        if (a == 0) {
            a = 1;
            
            if (st > lastScrollTop) {
            /* SCROLLING DOWN */
                wh = $(window).scrollTop() + window.innerHeight;
                $("html, body").stop().animate({scrollTop: wh}, 700, function () {
                    a = 0;
                });

            } else {
            /* SCROLLING UP */
                wh = $(window).scrollTop() - window.innerHeight;
                $("html, body").stop().animate({scrollTop: wh}, 700, function () {
                    a = 0;
                });
            }
            
            lastScrollTop = st;
        }
    });
body {
  margin: 0;
}

p {
  margin: 0;
  font-size: 70px;
  color: #fff;
}

.section {
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="section" style="background:rgb(100,100,255)">
  <p>Blue</p>
</div>
<div class="section" style="background:rgb(60,150,60)">
  <p>Green</p>
</div>
<div class="section" style="background:rgb(180,30,30)">
  <p>Red</p>
</div>
<div class="section" style="background:rgb(80,0,0)">
  <p>Brown</p>
</div>
<div class="section" style="background:rgb(0,0,0)">
  <p>Black</p>
</div>
  • See [Infinite auto scroll with dynamic content e.g. append](https://stackoverflow.com/questions/28800685/infinite-auto-scroll-with-dynamic-content-e-g-append) – guest271314 Feb 24 '19 at 17:51

2 Answers2

0

The scroll event is triggered after the window has started scrolling so that event was a little laggy. What about capturing the mousewheel events as shown in Mousewheel event in modern browsers and also storing a boolean while the scroll is happening?

I refactored your code a little to remove duplicate code and use fewer variables with more readable names. You could use let instead of var and a ternary statement instead of the if/else block to shorten it further.

var scrollTop = $(window).scrollTop();
var isScrolling = false;

var myitem = window;
if (myitem.addEventListener)
{
    // IE9, Chrome, Safari, Opera
    myitem.addEventListener("mousewheel", MouseWheelHandler, false);
    // Firefox
    myitem.addEventListener("DOMMouseScroll", MouseWheelHandler, false);
}
// IE 6/7/8
else
{
    myitem.attachEvent("onmousewheel", MouseWheelHandler);
}

function MouseWheelHandler(e) {
    // cross-browser wheel delta
    var e = window.event || e; // old IE support
    var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
    e.preventDefault();  
    
  if (isScrolling ) {   
    return;
  } else { 
    isScrolling = true;
  }

  if (delta < 0 ) {
    scrollTop = scrollTop + window.innerHeight;
  } else {
    scrollTop = scrollTop - window.innerHeight;
  }

  $("html, body").stop().animate({
    scrollTop: scrollTop
  }, 700, function() {
    scrollTop = $(window).scrollTop();
    isScrolling = false;
  });

}
body {
  margin: 0;
}

p {
  margin: 0;
  font-size: 70px;
  color: #fff;
}

.section {
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="section" style="background:rgb(100,100,255)">
  <p>Blue</p>
</div>
<div class="section" style="background:rgb(60,150,60)">
  <p>Green</p>
</div>
<div class="section" style="background:rgb(180,30,30)">
  <p>Red</p>
</div>
<div class="section" style="background:rgb(80,0,0)">
  <p>Brown</p>
</div>
<div class="section" style="background:rgb(0,0,0)">
  <p>Black</p>
</div>
JasonB
  • 6,243
  • 2
  • 17
  • 27
  • Side note - there was a horizontal scrollbar in the stack snippet so I used `width: 100%;` instead of `width: 100vw;` – JasonB Feb 24 '19 at 18:17
  • Yes! Exactly what I was looking for! Thank you. – Michal Kučera Feb 25 '19 at 19:47
  • Sometimes its kinda "laggy", do you have any idea why is that? – Michal Kučera Feb 25 '19 at 19:49
  • I'm not seeing the lag, maybe add a console.log call inside the window.scroll handler to see if it's getting called too often and then add something like an underscore debounce to it. Maybe changing the speed down to less than 700... Are you able to share your development link so we can see it in action? – JasonB Feb 25 '19 at 21:47
  • It happens when you scroll too "wildly". It jumps to different sections etc. – Michal Kučera Mar 03 '19 at 07:36
  • Sure, I was able to duplicate that. I changed the answer to use a different method - I didn't see it had been accepted. Hopefully this will work better anyway! – JasonB Mar 03 '19 at 08:18
  • Woah, you are awesome! Thank you a lot! – Michal Kučera Mar 03 '19 at 09:39
-1

So, the term one page scroll is new for me, but I have googled it and understand what is your problem.
If you have various divs that have page behaviour, but these divs are just in one single page, then window.innerHeight Will only return the position of this single Page bottom. That is the last div Page. To solve this you can put ids on each div, then use jQuery scroll handler to scroll to that id. Or you can use this http://www.thepetedesign.com/demos/onepage_scroll_demo.html#