2014-03-18 66 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

相關問題