使用jQuery时,防止通过动画scrollTop触发滚动事件

我正在制作一个单页滑块插件,我有一个滚动事件回调,其中包含一个动画scrollTop ,再次触发滚动事件并陷入循环。 我尝试了一些诸如旗帜之类的东西,但似乎没有一件对我有用。

这模仿了以下内容:

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

滚动在固定步骤中受约束的情况下,跳转到上一个或下一个元素,这些元素都占据页面的整个高度。

代码如下:

 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事件之前触发。 请注意,似乎只有在出于某种原因向下滚动时才会发生。

在尝试了两步锁定之后,我使用了一个带有3个状态的标志来取消最终scroll事件,这非常有效,我进一步探索,因为它与原始代码中存在的翻转逻辑不太合作(跳转到到达终点时的另一端)。

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

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

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

这个jsfiddle提供了一个工作演示

HTML:

 

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)