Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
109 views
in Technique[技术] by (71.8m points)

javascript - Treating each div as a "page" when scrolling

I have a page that I'm building and I would like to make it that when I scroll (up or down) the page scrolls to the next div (each div is 100% the height of the window). And gets "fixed" there until you scroll again. An example of what I'm trying to accomplish can be seen here:

http://testdays.hondamoto.ch/

You will notice that when you scroll down, it automatically moves you to the next "div".

What I've tried:

  • Using the jQuery .scroll event combined with:

        function updatePosition() {
          if(canScroll) {
            var pageName;
            canScroll = false;
            var st = $(window).scrollTop();
            if (st > lastScrollTop){
               // downscroll code
               if(pageNumber < 7) {
                   pageNumber++;
               }
               pageName = '#' + getPageToScrollTo().id;
               $('body').animate({ scrollTop: $(pageName).offset().top }, 2000, function() {
                   canScroll = true;
               });
            } else {
              // upscroll code
              if(pageNumber > 0) {
                  pageNumber--;
              }
              pageName = '#' + getPageToScrollTo().id;
              $('body').animate({ scrollTop: $(pageName).offset().top }, 2000, function() {
                   canScroll = true;
                });
            }
            lastScrollTop = st;
          }
        }
    

But the scroll event was getting called when the page was scrolling (animating), AND when the user scrolled. I only need it to be called when the user scrolls.

Then I added:

var throttled = _.throttle(updatePosition, 3000);

$(document).scroll(throttled);

From the Underscore.js library - but it still did the same.

Finally, I browsed here a bit and found:

Call Scroll only when user scrolls, not when animate()

But I was unable to implement that solution. Is there anyone that knows of any libraries or methods to get this working?

EDIT: Solution based on Basic's answer:

  function nextPage() {
        canScroll = false;
        if(pageNumber < 7) {
            pageNumber++;
        }
        pageName = getPageToScrollTo();
        $('html, body').stop().animate({ scrollTop: $(pageName).offset().top }, 1000, function() {
            canScroll = true;
        });
    }

    function prevPage() {
        canScroll = false;
        if(pageNumber > 0) {
        pageNumber--;
      }
      pageName = getPageToScrollTo();
      $('html, body').stop().animate({ scrollTop: $(pageName).offset().top }, 1000, function() {
         canScroll = true;
      });
    }

    //--Bind mouseWheel
    $(window).on(mousewheelevt, function(event) {
        event.preventDefault();
        if(canScroll){
          if(mousewheelevt == "mousewheel") {
              if (event.originalEvent.wheelDelta >= 0) {
                prevPage();
              } else {
                nextPage();
              }
          } else if(mousewheelevt == "DOMMouseScroll") {
              if (event.originalEvent.detail >= 0) {
                nextPage();
              } else {
                prevPage();
              }
          }
        }
    });
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Ok...

The relevant code for the Honda site can be found in http://testdays.hondamoto.ch/js/script_2.js. It seems to be doing some calculations to locate the top of the div then scroll to it. There are handlers for different types of scrolling.

Specifically, the movement is handled by function navigation(target)

the key bits is here...

$('html,body').stop().animate({
        scrollTop: $(target).offset().top + newMargin
    }, 1000,'easeInOutExpo',function(){
        //Lots of "page"-specific stuff
    }
});

There are handlers for the scroll types...

$('body').bind('touchstart', function(event) {
    //if(currentNav!=3){
        // jQuery clones events, but only with a limited number of properties for perf reasons. Need the original event to get 'touches'
        var e = event.originalEvent;
        scrollStartPos = e.touches[0].pageY;
    //}
});

//--Bind mouseWheel
$('*').bind('mousewheel', function(event, delta) {
    event.preventDefault();
    //trace('class : '+$(this).attr('class') + '   id : '+$(this).attr('id'));
    if(!busy && !lockScrollModel && !lockScrollMap){
        if(delta<0){
            nextPage();
        }else{
            prevPage();
        }
    }
});

You'll note that the navigate() function sets a busy flag which is unset when scrolling completes - which is how it suppresses all new scroll events during a scroll. Try changing the direction of scroll while the page is already scrolling and you'll notice user input is being ignored too.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...