简体   繁体   中英

jQuery animate once on scroll

I have a simple script that basically waits till my navigation has scrolled off the screen, resizes it slightly then it animates in from the top of the screen and remains fixed till i scroll back up.

When you scroll past the menu it animates back in, but then repeats this animation every time I finish scrolling. I have tried adding the animation outside of the scroll function but then it doesn't animate at all.

Have i missed something simple?

    var Header = $('#header'),
        Navbar = $('.navbar'),
        links = $(".navbar ul.nav > li > a"),
        HeaderH = Header.height(),
        NavbarH = Navbar.height();

$(window).scroll(function () {

    if ($(this).scrollTop() > (HeaderH + NavbarH)) {
        Navbar.addClass('navbar-fixed-top')
        links.css('padding', '10px 20px 10px 20px');
        Header.css('margin-bottom', '64px');
        Navbar.css('top', '-64px').animate({'top' : '0'}, 1000);

    }
    else{
        Navbar.removeClass('navbar-fixed-top')
        links.css('padding', '20px');
    }
});

The site is built on joomla with bootstrap, hence the navbar-fixed-top style classes.

Your scroll handler will be called multiple times as the user scrolls.

To illustrate this, if you add a console log

    $(window).on('scroll', function(){
    console.log('scroll');
});

You'll see "scroll" output multiple times as you scroll down. This is because each little gradation of scroll fires off a scroll event.

A common approach is to wrap your callback in a debounce function, so it only runs once in a given period, even if more scroll events are fired.

  • Include the throttle/debounce jQuery plugin in your page - get it from http://benalman.com/projects/jquery-throttle-debounce-plugin/ .
  • Tweak your code like so:

    function scrollHandler() {

      if ($(this).scrollTop() > (HeaderH + NavbarH)) { Navbar.addClass('navbar-fixed-top') links.css('padding', '10px 20px 10px 20px'); Header.css('margin-bottom', '64px'); Navbar.css('top', '-64px').animate({'top': '0'}, 1000); } else { Navbar.removeClass('navbar-fixed-top') links.css('padding', '20px'); } } $(window).scroll($.debounce(750, scrollHandler)); 

This will make it respond only for one scroll event per 750 milliseconds - change the duration to your taste.

Stackoverflow code block is freaking out for some reason - please note the "function scrollHandler(){" line above.

A more economical approach

A more concise way of doing the same thing is to check if the scroll event's been fired in a given period and if it hasn't to assume the user's stopped scrolling. This solution is borrowed from this other question .

function scrollHandler() {
    if ($(this).scrollTop() > (HeaderH + NavbarH)) {
        Navbar.addClass('navbar-fixed-top');
        links.css('padding', '10px 20px 10px 20px');
        Header.css('margin-bottom', '64px');
        Navbar.css('top', '-64px').animate({'top': '0'}, 1000);
    }
    else {
        Navbar.removeClass('navbar-fixed-top');
        links.css('padding', '20px');
    }
}

$(window).on('scroll', function () {
    clearTimeout($.data(this, 'timer'));
    $.data(this, 'timer', setTimeout(function () {
        scrollHandler();
    }, 250));
});

This method doesn't give you the same options and potential for re-use you get with the debounce plugin - the plugin lets you choose whether to call your callback at the start or the end of your period - but it's slimmer.

Try something like

    var Header = $('#header'),
    Navbar = $('.navbar'),
    links = $(".navbar ul.nav > li > a"),
    HeaderH = Header.height(),
    NavbarH = Navbar.height();
    var scrolled = false;

$(window).scroll(function () {

 if ($(this).scrollTop() > (HeaderH + NavbarH) && !scrolled) {
    Navbar.addClass('navbar-fixed-top')
    links.css('padding', '10px 20px 10px 20px');
    Header.css('margin-bottom', '64px');
    Navbar.css('top', '-64px').animate({'top' : '0'}, 1000);
    scrolled = true;
 }
 else{
    Navbar.removeClass('navbar-fixed-top')
    links.css('padding', '20px');
    scrolled = false;
 }
});

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