Javascript 使用jQuery时防止动画scrollTop触发滚动事件

Javascript 使用jQuery时防止动画scrollTop触发滚动事件,javascript,jquery,Javascript,Jquery,我正在编写一个全屏滚动脚本。它应该以固定的步骤滚动到上一个或下一个元素,每个元素通常占据页面的整个高度 我有一个滚动事件回调,其中包含一个动画的scrollTop,再次触发滚动事件并陷入循环。我试过一些东西,比如旗子,但没有一件对我有用 代码如下: function pageDown() { // Some stuff, not important if (currentIndex+1 === pageCount) nextIndex = 0; else nextInde

我正在编写一个全屏滚动脚本。它应该以固定的步骤滚动到上一个或下一个元素,每个元素通常占据页面的整个高度

我有一个滚动事件回调,其中包含一个动画的
scrollTop
,再次触发滚动事件并陷入循环。我试过一些东西,比如旗子,但没有一件对我有用

代码如下:

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的
animate
complete
回调在它生成的最后一个
scroll
事件之前触发。请注意,这似乎只有在出于某种原因向下滚动时才会发生

在试验了2步锁之后,我使用了一个带有3个状态的标志来取消最后的
滚动事件,这一点效果相当好,我进一步探索了它,因为它与原始代码中的滚动逻辑(到达终点时跳到另一端)不太协调

我想出了下面的代码,它记录了要到达的目标位置,只要当前位置与目标不匹配,就会忽略所有的
滚动事件

这还实现了滚动逻辑,并且必须与相关的HTML和CSS结合才能正常工作,因为我们需要一些空白空间(这里每侧都有一个像素),以允许在顶部和底部触发
滚动
事件。我们还启动第一个滚动,以便正确定位第一个元素,并允许滚动立即工作

我希望代码中的注释将提供理解所用逻辑所需的附加信息

本网站提供了一个工作演示

HTML:


CSS:

html,正文{
身高:100%;
保证金:0;
填充:0;
}
.页{
填充:1px0;
背景颜色:黄色;
}
.pageScroller,.page{
身高:100%;
}
.保险杠{
高度:1px;
}
JavaScript:

var$pages=$('.page');
var currentIndex=0;
var lastScroll=0;
var currentScroll=0;
var targetScroll=1;//必须设置为与第一个滚动相同的值
函数doScroll(newScroll){
$('html,body')。设置动画({
滚动顶端:新闻滚动
}, 400);   
}
$(窗口).on('scroll',function(){
//获取当前位置
currentScroll=$(窗口).scrollTop();
//穿越
如果(targetScroll==-1){
//未设置目标,允许在此处不执行任何操作来执行
}
//还在动
else if(currentScroll!=targetScroll){
//未达到目标,忽略此滚动事件
返回;
}
//达到目标
else if(currentScroll==targetScroll){
//更新滚动方向的比较器
lastScroll=currentScroll;
//启用直通
targetScroll=-1;
//忽略此滚动事件
返回;
}
//获取滚动方向
var dirUp=currentScroll>lastScroll?false:true;
//更新索引
currentIndex+=(dirUp?-1:1);
//出发前到达,跳到终点
如果(当前索引<0){
currentIndex=$pages.length-1;
}
//到达终点后,跳到起点
else if(currentIndex>=$pages.length){
currentIndex=0;
}    
//获取目标的滚动位置
targetScroll=$pages.eq(currentIndex).offset().top;
//滚动到目标
多斯克罗尔(目标卷轴);
});
//滚动到第一个元素
$(窗口)。滚动顶部(1)

当使用
鼠标滚轮时,这要容易得多。实际上,我制作了一个插件,可以做到这一点。它使用
requestAnimationFrame
滚动,并使用jqueryanimate回退,从而节省设备资源<代码>$(窗口).pulse({range:$(窗口).height(),delay:true})
。有了鼠标滚轮插件(包括在内),您可以检查它的导航方式。