使用jQuery时防止通过动画的scrollTop触发滚动事件 [英] Prevent triggering a scroll event by an animated scrollTop when using jQuery
问题描述
我正在开发一页滑块的插件,并且我有一个滚动事件回调,其中包含一个动画的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的animate
的complete
回调在其生成的最终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屋!