简体   繁体   中英

JQuery Jump to Anchors on Scroll

Aiming to do something similar to this where the page jumps to anchors on the page when you scroll down. I'm no expert with JQuery or JS in general (backend languages PHP and MySQL are my areas of preference) I grabbed a couple of scripts and put them together. There will be three anchors on the page, so it's meant to jump to the next one down when you scroll down and the next one up when you scroll up. However, when it scrolls to the second one it keeps scrolling past it even when I'm not still scrolling. This is the script:

var section = 1;

function scrollToAnchor(variable){
    var aTag = $("a[name='"+ variable +"']");
    $('html,body').animate({scrollTop: aTag.offset().top},'slow');
}

$(function(){
   //Keep track of last scroll
   var lastScroll = 0;
   $(window).scroll(function(event){
       //Sets the current scroll position
       var st = $(this).scrollTop();
       //Determines up-or-down scrolling
       if (st > lastScroll && section < 3){
          //Going down
           section = section + 1;
           scrollToAnchor('section'+section);
           lastScroll = st;
       } else if(st < lastScroll && section > 1){
          //Going up
           section = section - 1;
           scrollToAnchor('section'+section);
           lastScroll = st;
       }
       //Updates scroll position
       lastScroll = st;
   });
});

And the fiddle: http://jsfiddle.net/tBN64/4/

The reason is that when you scroll the scroll event is fired and then the animate function is scrolling to the element, but that animated scroll itself will fire the scroll event again resulting in a loop.

I suggest you try a different approach. You can for example catch the mousewheel direction and use that to scroll to the next element.

Example using the jQuery Mousewheel Plugin https://github.com/brandonaaron/jquery-mousewheel

var current_section = 1;
$(window).mousewheel(function (event, delta) {
    if (delta > 0) {
        current_section = current_section - 1; //up
        $('body, html').stop().animate({
            scrollTop: $('a[name="section' + current_section + '"]').offset().top
        }, 'slow');
    } else if (delta < 0) {
        current_section = current_section + 1; //down
        $('body, html').stop().animate({
            scrollTop: $('a[name="section' + current_section + '"]').offset().top
        }, 'slow');
    }
    return false;
});

Fiddle: http://jsfiddle.net/tBN64/6/ (the above code is at the end)

NOTE: This code does not verify if there is a next section , so if you scroll to much it will throw an error. You need to make sure the next element exists / if it doesn't don't animate to it. (see console for errors, usually if you press F12 in your browser)

There are more problems in your script. First - I think you need to prevent the default behavior of the scroll event, otherwise it will scroll, and you do not want that, as you want to animate scroll yourself.

event.preventDefault() could help and also a return false; at the end of the function.

Then the problem is, that the scroll event is not triggered once, but more times with one mouse scroll. You somehow need to prevent this, as otherwise it happens, that the scroll begins, then you animation starts, but the scroll is still going on, it passes Section 2, and is triggered again and again..

Maybe this script could help - it makes a new event scrollStopped :

jQuery - bind event on Scroll Stop

Generally I would advise you rather to search for a script that does this behavior, becasue programming it yourself can bring you to a lot of problems that other users may have fixed in the past in their plugins.

I have found some bugs using Spokey's answer , when the page scrolled too much we got a js error, so I added some checks: if the section is the last one, then we needn't raise its number, and the same for scrolling up.

I got this code, but changed this for sections, not anchors:

var current_section = 1;
var min_section = 1;
var max_section = $("section[name]").length;
$(window).mousewheel(function (event, delta) {
    if (delta > 0) {
        current_section = current_section - 1; //up
        if (current_section < min_section) current_section = min_section;
        $('body, html').stop().animate({
            scrollTop: $('section[name="section' + current_section + '"]').offset().top - 100
        }, 'slow');
    } else if (delta < 0) {
        current_section = current_section + 1; //down
        if (current_section > max_section) current_section = max_section;
        $('body, html').stop().animate({
            scrollTop: $('section[name="section' + current_section + '"]').offset().top - 100
        }, 'slow');
    }
    return false;
});

$('body, html').scroll(function(){ return false; }); // allow no scrolling

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM