jQuery Tools Scrollable with Mousewheel – 滚动一个位置并停止

我正在使用bind / unbind进行鼠标滚动,基于此SO响应:

Jquery,取消绑定鼠标滚轮事件,然后在操作完成后重新绑定它?

我正在从delta中挖掘事件树,只定位X鼠标滚轮值。 一切都运作良好。 我想克服的问题:我想简单地向前/向后滚动一个面板,然后停止滚动。 目前,我在移动后立即解除鼠标滚轮事件的绑定,并且有效地停止了滚动…但是解除鼠标滚轮事件的绑定也会使页面突然显示。 我需要的是能够嗅探方向的第一个deltaX值,然后移动并停止收听。 我是否需要查看自动滚动以获取答案? 绑定/解除绑定感觉很难,但我不能,为了我的生活,想象一下如何在一次移动后踢出,同时仍然能够在移动完成后滚动。 这是我的鼠标滚轮function:

function mouseHandler(event, delta) { $('.homeScrollable').bind('mousewheel', mouseHandler); var deltaX = event.originalEvent.wheelDeltaX; //console.log(event.originalEvent.wheelDeltaX); if(deltaX  0) { //move backward 1 screen and stop scrollapi.move(-1); $('.homeScrollable').unbind('mousewheel', mouseHandler); } event.preventDefault(); // Rebind mousewheel event: $('.homeScrollable').bind('mousewheel', mouseHandler); }; 

我也看过设置一个计时器,一个la:

jquery mousewheel插件:如何每次滚动只触发一个函数

这似乎令人难以置信,但没有去。 这是这个人的插件页面: http : //brandonaaron.net/code/mousewheel/docs

感谢检查出来。

由于DOM没有提供任何区分第一个滚动事件和后续碰撞事件的方法,因为我们不得不考虑区分它们的间接方法。

如果快速滚动浏览任何特定元素,则会按顺序多次触发滚动事件。 使用以下代码,我们可以准确了解发生的频率:

 $('#exampleDiv').bind('mousewheel', function () { console.log(new Date().getTime()); }); 

当您滚动该div时,您将获得如下所示的控制台输出:

 // Using mouse wheelbar 251327626600149 251327626600215 251327626600265 251327626600282 251327626600332 251327626600365 // Using touchpad 251327626626207 251327626626225 251327626626261 251327626626276 251327626626312 251327626626345 

看看这个输出,看起来mousescroll事件通常在20毫秒到60毫秒之间的某个地方被触发。 为了安全起见,我们将上限设为100 ms。 这是非常有用的信息,因为我们可以使用它来区分属于同一动作的滚动事件和可能由用户明确且故意启动的滚动事件。

你可以从这里做的是创建一个全局可访问的’timestamp’变量,每次触发mousescroll事件时更新它,无论是否成功。 像这样的东西:

 var timeStamp = new Date().getTime(); $('#exampleDiv').bind('mousewheel', function (event) { var timeNow = new Date().getTime(); // Need to prevent the default scrolling behavior event.preventDefault(); // If the last mousescroll happened less that 100 ms ago, update // timeStamp and do nothing if (timeNow - timeStamp < 100) { timeStamp = timeNow; return; } else { timeStamp = timeNow; scrollToSomeOtherDiv(); } }); 

这有效地忽略了在它们之前的初始事件之后触发的所有mousescroll事件,但在用户暂停100 ms后再次开始工作。

这将解决您的问题,除非您的scrollToSomeOtherDiv()函数涉及某种耗时的动画。 您当然可以创建一个全局布尔值isAnimating ,并在每次触发mousescroll事件时检查它是否为真(确保在动画结束后在回调中将其设置为false)。

这可行,除了它可以为用户提供刺耳的体验。 即使在看到动画开始后,想要快速滚动两个面板的人也可能不会在滚动之间暂停。 上面的代码将看到所有mousescroll事件作为相同滚动动作的一部分,并继续忽略它们!

在这种情况下,您可以简单地使用动画时间作为阈值。 您可以在动画开始后设置timeStamp,然后在该段时间内忽略所有mousescroll事件。 我在这里写了一个例子: http : //jsfiddle.net/Sg8JQ/

相关代码在这里:

 var lastAnimation = 0; var animationTime = 1000; // in ms var quietPeriod = 500; // in ms, time after animation to ignore mousescroll function scrollThis(event, delta, deltaX, deltaY) { var timeNow = new Date().getTime(); // change this to deltaX/deltaY depending on which // scrolling dir you want to capture deltaOfInterest = deltaY; if (deltaOfInterest == 0) { // Uncomment if you want to use deltaX // event.preventDefault(); return; } // Cancel scroll if currently animating or within quiet period if(timeNow - lastAnimation < quietPeriod + animationTime) { event.preventDefault(); return; } if (deltaOfInterest < 0) { if ($('.active').next('div').length) { lastAnimation = timeNow; $('.active').removeClass('active').next('div').addClass('active'); $('html,body').animate( { scrollTop: $('.active').offset().top }, animationTime); } } else { if ($('.active').prev('div').length) { lastAnimation = timeNow; $('.active').removeClass('active').prev('div').addClass('active'); $('html,body').animate( { scrollTop: $('.active').offset().top }, animationTime); } } } // Note: mousewheel() is defined in the mousewheel plugin by Brandon Aaron // You could do without it, but you'd need to adjust for firefox and webkit // separately. // // You couldn't use $(document).scroll() because it doesn't allow you to // preventDefault(), which I use here. $(document).mousewheel(scrollThis); 

我还包括quietPeriod ,这是超出动画时间的时间,在此期间你想继续忽略mousescroll事件。 如果您希望动画完成后滚动“响应”,则可以将其设置为0。

看看这个,看看你的想法。 首先,我不会绑定到鼠标滚轮,因为Firefox使用DOMMouseScroll。 这也使用了不同的delta处理程序,它与所有其他浏览器使用的处理程序相反。 而是绑定到jQuery的scroll事件,该事件规范化了行为。 您可以跟踪最后一个滚动顶部位置,以确定用户是向上还是向下滚动。

我有点假设你在各部分之间制作动画。 是否有回调函数可用于确定是否应该滚动? 我创建了一个全局来跟踪元素当前是否具有动画效果。 如果是这样,那么我们不打扰执行该function。 最后,我注意到滚动动画的回调似乎在最终滚动事件发生之前触发,所以我实际上必须在那里使用setTimeout。 我不喜欢它,但我无法弄清楚如何让回调正常工作。

http://jsfiddle.net/Gj3Qy/

 var lastScrollTop = 0; var isDoingStuff = false; $(document).scroll(function(event) { //abandon if(isDoingStuff) { return; } if ($(this).scrollTop() > lastScrollTop) { //console.log('down'); $('.active').removeClass('active').next('div').addClass('active'); isDoingStuff = true; $('html,body').animate( {scrollTop: $('.active').offset().top }, 1000, function() { setTimeout(function() {isDoingStuff = false;}, 100); console.log('off'); }); } else { //console.log('up'); } lastScrollTop = $(this).scrollTop(); }) 

所以,这就是我在做的事情。 它似乎工作,但仍然是马车。

 i=0; $("#test").mousewheel(function(event, delta) { event.preventDefault(); clearTimeout($.data(this, 'timer')); // check if the mouse moved on right/up if( delta > 0 ) { i++; // hack to execute function just once if( i == 3 ) { $('#child').fadeIn().html("

next

").fadeOut(); // do something once when i=4, but happening multiple times } } else { // check if mouse moved left/down i--; if(i==-3) { $('#child').fadeIn().html("

previous

").fadeOut(); // do something once when i=-4, but happening multiple times } } // end if delta // only execute another mousewheel scroll after some delay $.data(this, 'timer', setTimeout(function() { i = 0; }, 100)); });

因此,虽然增加的i打印得很好,但如果我取消注释if i = 4打印行,它就无法正常工作(如果使用鼠标,我可能需要滚动,我在触控板上尝试)。 虽然我理解它,因为当你得到delta值时我不断增加,你只有当我达到4并且只在滚动停止250ms时才重置它的值,这段代码似乎将i重置为0至少两次或三次所以我== 4实际执行两次或三次。 也许你可以找到可能发生的事情。 我几乎就在那里,只需要修复那个bug。

尝试在if(i == 4)语句中添加更改为fadeIn,fadeOut效果的内容,并使其更加突出。

编辑:

这是新编辑的版本 。 鼠标滚轮链接很旧,所以现在可能会更好。 如果你快速移动,你会看到它闪烁……

我认为“pikappa”提供的解决方案是纯粹的性感。

对我而言,它在firefox上完美运行但我在Chrome 26.0.x下滚动时遇到了“闪烁”

他惊人的代码的一个简单的“补丁”是在他的 JSfiddle的第57和64行添加“ return false;