2014-03-18 71 views
2

我正在构建幻灯片上的变体,其中幻灯片淡入/淡出时用户向上/向下滚动。其基本过程是这样的:防止onScroll函数再次执行直到完成

  1. 用户将其滚轮
  2. 检测与$(window).on('DOMMouseScroll mousewheel')
  3. 运动检测如果滚动是向上或向下,并跟踪它有多少滚动
  4. 一旦滚动量在任一方向达到阈值,根据滚动方向显示上一张/下一张幻灯片

问题是在某些设备上,特别是跟踪板和“魔术”鼠标(tou ch),onScroll函数执行多次。我希望该功能运行一次,完成,然后再次运行之前等待其他onScroll事件。

这里是我的代码的简化版本。

$(function() { 


    var delta = 0; 
    var wait = false; 
    var scrollThreshold = 5; 

    $(window).on('DOMMouseScroll mousewheel', function(e){ 

    if (wait === false) { 

     // If the scroll is up 
     if (e.originalEvent.detail < 0 || e.originalEvent.wheelDelta > 0) { 

     // Track the amount of scroll 
     delta = Math.min(0,delta - 1); 

     if (Math.abs(delta) >= scrollThreshold) { 


      wait = true; 

      // Go to the previous slide 
      // This changes the class of the current and previous slides 
      // causing several CSS transitions. 
      $(active).removeClass('active'); 
      $(prev).addClass('active').removeClass('zoom'); 

      $(active, prev).one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(e) { 

      wait = false; 
      delta = 0; 

      }); 

     } 

     // If the scroll is down 
     } else { 

     // Track the amount of scroll 
     delta = Math.max(0,delta + 1); 

     if (Math.abs(delta) >= scrollThreshold) { 

      wait = true; 

      // Go to the next slide 
      // This changes the class of the current and next slides 
      // causing several CSS transitions. 
      $(active).addClass('zoom').removeClass('active'); 
      $(next).addClass('active'); 

      $(active, next).one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(e) {  

      wait = false; 
      delta = 0; 

      }); 

     } 

     } 

    } 

    }); 

的问题是wait标志不防止函数在触摸板和“魔力”鼠标再次运行。

推荐使函数运行一次的方法是什么,然后等到它完成之后再监听新的滚动事件并再次运行?

回答

0

如果你正在使用underscorejs库(它的梦幻般的),有一个名为_.debounce的函数可以完成你正在尝试做的事情。

这里是该函数的代码。从库中的评论解释了它完美:-)

// Returns a function, that, as long as it continues to be invoked, will not 
// be triggered. The function will be called after it stops being called for 
// N milliseconds. If `immediate` is passed, trigger the function on the 
// leading edge, instead of the trailing. 
_.debounce = function(func, wait, immediate) { 
    var timeout; 
    return function() { 
     var context = this, args = arguments; 
     var later = function() { 
      timeout = null; 
      if (!immediate) func.apply(context, args); 
     }; 
     var callNow = immediate && !timeout; 
     clearTimeout(timeout); 
     timeout = setTimeout(later, wait); 
     if (callNow) func.apply(context, args); 
    }; 
}; 

编辑:这里是David Walsh重构这一功能自行

function debounce(func, wait, immediate) { 
    var timeout; 
    return function() { 
     var context = this, args = arguments; 
     clearTimeout(timeout); 
     timeout = setTimeout(function() { 
      timeout = null; 
      if (!immediate) func.apply(context, args); 
     }, wait); 
     if (immediate && !timeout) func.apply(context, args); 
    }; 
}; 

用法示例

var myEfficientFn = debounce(function() { 
    // All the taxing stuff you do 
}, 250); 

window.addEventListener('resize', myEfficientFn); 
+0

令人感兴趣的应用代码。如果有可能没有额外的JS库,我更喜欢那条路线。然而,我会保持这种情况。 –

+0

也有一些自定义的jQuery'.debounce()'函数,但我所看到的函数是基于时间而不是滚动的数量,不幸的是。 –

+0

我将其更新为包含一个可以在不包含其他库的情况下自行使用的函数。来源是David Walsh。 – lommaj

相关问题