简体   繁体   中英

Detect change in scroll direction with jQuery

I am using a basic jQuery function to toggle some classes to a div when scrolling up or down.

Basically it works this way:

  • When the user scrolls down, add the class "is-header-hidden", remove the class "is-header-visible"
  • When the user scrolls up, add the class "is-header-visible", remove the class "is-header-hidden"

Here's my code:

function hidingHeader() {

    var didScroll,
        lastScrollTop = 0,
        tolerance = 15,
        header = $('header'),
        headerHeight = header.outerHeight(true),
        fixedClass = ('is-header-fixed'),
        hiddenClass = ('is-header-hidden'),
        visibleClass = ('is-header-visible'),
        transitioningClass = ('is-header-transitioning');

    win.scroll(function( event ) {
        didScroll = true;
    });

    setInterval(function() {
        if ( didScroll ) {
            hasScrolled();
            didScroll = false;
        }
    }, 250);

    function hasScrolled() {
        var st = $(this).scrollTop();

        // SCROLL DOWN
        if( st > lastScrollTop ) {

            header.removeClass( visibleClass );
            if( st >= headerHeight ) {
                header.addClass( fixedClass ).addClass( hiddenClass );
            }

        // SCROLL UP
        } else {
            // Make sure they scroll more than tolerance
            if( Math.abs( lastScrollTop - st ) > tolerance ) {
                header.removeClass( hiddenClass ).addClass( visibleClass );
            }
        }

        // UPDATE SCROLL VAR
        var lastScrollTop = st;
    }
}

Now, I want to add an "is-transitioning" class containing CSS transform attributes, that I am going to remove with a CSS animation callback . The problem is that I need that class to be triggered once , in other words only when there's a change in scroll direction, not every time the user scrolls.

I thought to store a "second to last" scrollTop variable in order to detect when there is a change in scroll direction, but my attempts failed. Any advice?

Maybe something like this?

function hidingHeader() {

var didScroll,
    lastScrollTop = 0,
    tolerance = 15,
    lastDir = null,  // you can start with a non-null if you don't want to trigger the first down for example, make this lastDir = "down",
    header = $('header'),
    headerHeight = header.outerHeight(true),
    fixedClass = ('is-header-fixed'),
    hiddenClass = ('is-header-hidden'),
    visibleClass = ('is-header-visible'),
    transitioningClass = ('is-header-transitioning');

win.scroll(function( event ) {
    didScroll = true;
});

setInterval(function() {
    if ( didScroll ) {
        hasScrolled();
        didScroll = false;
    }
}, 250);

function hasScrolled() {
    var st = $(this).scrollTop();

    // SCROLL DOWN
    if( st > lastScrollTop ) {

        header.removeClass( visibleClass );
        if( st >= headerHeight ) {
            header.addClass( fixedClass ).addClass( hiddenClass );
        }

        if( lastDir !== "down" ) { // Should only get triggered once while scrolling down, the first time the direction change happens
            lastDir = "down";
            // do your transition stuff here
        }

    // SCROLL UP
    } else {
        // Make sure they scroll more than tolerance
        if( Math.abs( lastScrollTop - st ) > tolerance ) {
            header.removeClass( hiddenClass ).addClass( visibleClass );
        }

        if( lastDir !== "up" ) { // Should only get triggered once while scrolling up, the first time the direction change happens
            lastDir = "up";
            // do your transition stuff here
        }
    }

    // UPDATE SCROLL VAR
    var lastScrollTop = st;
}

}

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