Prevent triggering a scroll event by an animated scrollTop when using jQuery

前端 未结 1 1363
我寻月下人不归
我寻月下人不归 2021-01-14 07:16

I am working on a fullscreen scrolling script. It is supposed to scroll in fixed steps, to the previous or next element, each typically occupying the full height of the page

相关标签:
1条回答
  • 2021-01-14 07:22

    The main issue I have witnessed when testing this out is that the complete callback of jQuery's animate fires before the final scroll event it generates. Note that seems to only happen when scrolling down for some reason.

    After experimenting with a 2 steps lock, where I used a flag with 3 states to cancel that final scroll event, which worked fairly well, I explored further as it was less cooperative with the rollover logic that is present in your original code (jumping to the opposite end when reaching an end).

    I came up with the following code, which records the target position to be reached and ignores all scroll events as long as the current position does not match the target.

    This also implements the rollover logic and must be combined with the associated HTML and CSS to work properly, as we need some blank space (a single pixel on each side here) to allow for a scroll event to be fired at the top and bottom. We also initiate a first scroll as to correctly position the first element and allow the rollover to work immediately.

    I hope the comments in the code will provide the additional information necessary to understand the logic being used.

    A working demo is available in this jsfiddle

    HTML:

    <div class="pageScroller">
        <div class="bumper"></div>
        <div class="page" style="background-color:red;"></div>
        <div class="page" style="background-color:green;"></div>
        <div class="page" style="background-color:blue;"></div>
        <div class="page" style="background-color:violet;"></div>
        <div class="page" style="background-color:cyan;"></div>
        <div class="bumper"></div>
    </div>
    

    CSS:

    html, body {
        height:100%;
        margin:0;
        padding:0;
    }
    .pages {
        padding:1px 0;
        background-color:yellow;
    }
    .pageScroller, .page {
        height:100%;
    }
    .bumper {
        height:1px;    
    }
    

    JavaScript:

    var $pages = $('.page');
    
    var currentIndex  = 0;
    
    var lastScroll    = 0;
    var currentScroll = 0;
    var targetScroll  = 1; // must be set to the same value as the first scroll
    
    function doScroll(newScroll) {
    
        $('html, body').animate({
            scrollTop: newScroll
        }, 400);   
    }
    
    $(window).on('scroll', function() {
    
        // get current position
        currentScroll = $(window).scrollTop();
    
        // passthrough
        if(targetScroll == -1) {
            // no target set, allow execution by doing nothing here
        }
        // still moving
        else if(currentScroll != targetScroll) {
            // target not reached, ignore this scroll event
            return;
        }
        // reached target
        else if(currentScroll == targetScroll) {
            // update comparator for scroll direction
            lastScroll = currentScroll;
            // enable passthrough
            targetScroll = -1;
            // ignore this scroll event
            return;
        }
    
        // get scroll direction
        var dirUp = currentScroll > lastScroll ? false : true;
    
        // update index
        currentIndex += (dirUp ? -1 : 1);
    
        // reached before start, jump to end
        if(currentIndex < 0) {
            currentIndex = $pages.length-1;
        }
        // reached after end, jump to start
        else if(currentIndex >= $pages.length) {
            currentIndex = 0;
        }    
    
        // get scroll position of target
        targetScroll = $pages.eq(currentIndex).offset().top;
    
        // scroll to target
        doScroll(targetScroll);   
    });
    
    // scroll to first element
    $(window).scrollTop(1)
    
    0 讨论(0)
提交回复
热议问题