使用jQuery时防止通过动画的scrollTop触发滚动事件 [英] Prevent triggering a scroll event by an animated scrollTop when using jQuery

查看:100
本文介绍了使用jQuery时防止通过动画的scrollTop触发滚动事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一页滑块的插件,并且我有一个滚动事件回调,其中包含一个动画的scrollTop,再次触发了滚动事件并陷入了循环.我尝试了一些诸如标志的操作,但似乎没有一种对我有用.

I am working on a one-page-slider plugin, and I have a scroll event callback which contains an animated scrollTop, triggering the scroll event again and getting caught in a loop. I have tried a few things such as flags, but none seem to work for me.

这类似于以下内容:

http://alvarotrigo.com/fullPage/examples/scrollBar.html

在固定位置限制滚动的位置,跳转到上一个或下一个元素,这些元素全部占据了页面的整个高度.

Where scrolling is constrained in fixed steps, jumping to the previous or next element, which all occupy the full height of the page.

代码如下:

function pageDown() {
    // Some stuff, not important
    if (currentIndex+1 === pageCount) nextIndex = 0;
    else nextIndex = currentIndex+1;
    nextPage = $pages.eq(nextIndex);

    // Important stuff
    $('html body').animate({
        scrollTop: nextPage.offset().top
     }, 400, function() {preventScroll=false});
}

function pageUp() {
    // Some stuff, not important
    if (currentIndex === 0) nextIndex = pageCount-1;
    else nextIndex = currentIndex-1;
    nextPage = $pages.eq(nextIndex);

    // Important stuff
    $('html body').animate({
        scrollTop: nextPage.offset().top
     }, 400, function() {preventScroll=false});
}

var lastScroll = 0,
    preventScroll = false;
$(window).on('scroll', function() {
    var currentScroll = $(window).scrollTop();
    if(!preventScroll) {
        preventScroll = true;
        if (currentScroll > lastScroll) pageDown();
        else pageUp();
    }
    lastScroll = currentScroll;
});

推荐答案

测试时我看到的主要问题是,jQuery的animatecomplete回调在其生成的最终scroll事件之前触发.请注意,这似乎仅在出于某些原因向下滚动时发生.

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.

尝试了2个步骤的锁之后,我使用了带有3个状态的标志来取消最后一个scroll事件,该方法效果很好,因此我进行了进一步的探索,因为它与您的现有翻转逻辑不太合作原始代码(到达末尾时跳到另一端).

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).

我想出了以下代码,该代码记录了要达到的目标位置,并忽略了所有scroll事件,只要当前位置与目标位置不匹配即可.

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.

这也实现了翻转逻辑,并且必须与关联的HTML和CSS结合使用才能正常工作,因为我们需要一些空格(此处每侧各有一个像素)以允许触发scroll事件顶部和底部.我们还启动了第一个滚动,以正确定位第一个元素并允许翻转立即进行.

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.

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:

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)

这篇关于使用jQuery时防止通过动画的scrollTop触发滚动事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆