2012-03-08 15 views
42

मेरे पास "अनंत स्क्रॉल" वाला एक पृष्ठ है। यह पृष्ठ के अंत और वर्तमान पृष्ठ के बीच के अंतर की गणना करता है और यदि यह अंतर पर्याप्त छोटा है तो अधिक सामग्री लोड करता है। कोड इस jQuery का उपयोग कर की तरह soemthing है:स्क्रॉल घटना कई बार फायरिंग। मैं केवल इसे अधिकतम कह सकता हूं, एक बार प्रति सेकंड

$(window).on('scroll', function() { 
    if (window.pageYOffset > loadMoreButton.offsetTop - 1000) 
     # load more content via ajax 
} 

अब, समस्या यह है कि हर बार जब मैं स्क्रॉल, इस घटना को प्रति स्क्रॉल कई बार सक्रिय करता है। मैं हर एक्स मिलीसेकंड पर आग लगाना चाहूंगा। यह मैं कैसे करूंगा?

उत्तर

37

Underscore.js लाइब्रेरी की "थ्रॉटल" विधि देखें।

http://underscorejs.org/#throttle

उदाहरण यह देता है आप वास्तव में क्या बारे में पूछ रहे है - सीमित कि आप कितनी बार स्क्रॉल ईवेंट को संभालने के लिए है।

+2

बहुत भयानक पुस्तकालय, लेकिन मैं किसी भी निर्भरता से बचने के लिए कोशिश कर रहा हूँ। –

+14

अंडरस्कोर को स्रोत कोड देखें (जिसे बेहद प्रलेखित किया गया है) और केवल थ्रॉटल खींचें। – tkone

0

स्क्रॉल आग कई बार सही है और आपको प्रत्येक बार स्क्रॉल स्थिति अलग-अलग प्राप्त करने में सक्षम होना चाहिए। मुझे लगता है कि जब आप पहले स्क्रॉल इवेंट में जाते हैं तो आपको टाइमर सेट करने की आवश्यकता होती है जैसे कि आपने एक्स मिलीसेकंड का उल्लेख किया है, और टाइम स्टैम्प भी रिकॉर्ड किया है, और फिर अगली बार इवेंट फायर स्क्रॉल करें, अंतिम ट्रिगर टाइम देखें और इसे एक्स मिलीसेकंड के भीतर अनदेखा करें , और अपने टाइमर कार्रवाई में असली काम करते हैं। इस समस्या को हल करने के लिए

6
var isWorking = 0; 

$(window).on('scroll', function() 
{ 
    if(isWorking==0) 
    { 
     isWorking=1; 
     if (window.pageYOffset > loadMoreButton.offsetTop - 1000) 
     # load more content via ajax 
     setTimeout(function(){isWorking=0},1000); 
    } 
} 
+0

मुझे उम्मीद है कि यह काम कर रहा है, इसका परीक्षण नहीं किया। यह मूल रूप से प्रत्येक स्क्रॉल लॉन्च करता है लेकिन अगर कोई और प्रति चल रही है तो यह कुछ भी नहीं करती है, अगर नहीं तो यह xxx मिलीसेकंड की प्रतीक्षा करता है और नौकरी –

+0

ईइक करता है। आप जावास्क्रिप्ट में इस तरह नींद समारोह का उपयोग नहीं कर सकते हैं। यह नींद के दौरान ब्राउज़र लटका होगा। जावास्क्रिप्ट एकल थ्रेडेड है और ब्राउजर को ब्लॉक करता है। आप इस तरह जावास्क्रिप्ट कोड नहीं लिख सकते हैं। – jfriend00

+0

हाँ आप सही हैं, इस –

30

एक तरह से एक समय अंतराल को परिभाषित करने और केवल उस समय अंतराल के भीतर एक बार एक स्क्रॉल घटना पर कार्रवाई करने के लिए है। यदि उस समय अंतराल के दौरान एक से अधिक स्क्रॉल ईवेंट आते हैं, तो आप इसे अनदेखा करते हैं और केवल उस समय संसाधित करते हैं जब उस समय अंतराल पारित हो जाता है।

var scrollTimer, lastScrollFireTime = 0; 

$(window).on('scroll', function() { 

    var minScrollTime = 100; 
    var now = new Date().getTime(); 

    function processScroll() { 
     console.log(new Date().getTime().toString()); 
    } 

    if (!scrollTimer) { 
     if (now - lastScrollFireTime > (3 * minScrollTime)) { 
      processScroll(); // fire immediately on first scroll 
      lastScrollFireTime = now; 
     } 
     scrollTimer = setTimeout(function() { 
      scrollTimer = null; 
      lastScrollFireTime = new Date().getTime(); 
      processScroll(); 
     }, minScrollTime); 
    } 
}); 

यह तुरंत पहले स्क्रॉल ईवेंट को सक्रिय और फिर आप एक स्क्रॉल घटना जबकि स्क्रॉलबार जाया जा रहा है और उसके बाद एक अंतिम घटना के बाद स्क्रॉलबार चलती बंद हो जाता है लगभग एक बार हर 100ms मिल जाएगा। आप setTimeout (वर्तमान में 100 पर सेट होने पर) को तर्क बदलकर ईवेंट की आवृत्ति समायोजित कर सकते हैं।

यहां एक डेमो है: http://jsfiddle.net/jfriend00/EBEqZ/ जो आपको डीबग कंसोल विंडो खोलने की आवश्यकता है, सामग्री विंडो में स्क्रॉलबार को ले जाना शुरू करें और फिर डीबग कंसोल विंडो में प्रत्येक स्क्रॉल ईवेंट का समय देखें। क्रोम के मेरे संस्करण पर, वे 100ms की न्यूनतम दूरी के लिए सेट हैं और वे हर 100-200ms होते हैं।

+0

हाय जिफ्रेंड, जब मैं अपने अनंत पृष्ठ पर कीबोर्ड की "एंड" कुंजी दबाता हूं, तो ऐसा लगता है कि प्रक्रिया स्क्रॉल दो बार आग लगती है। मैं इसे कैसे हल कर सकता हूं? – horse

+0

@ user2356198 - यहां एक संस्करण है जो उस समस्या को हल करता है: http://jsfiddle.net/v8e7aLy6/ – jfriend00

+0

यह "अंत" कुंजी के लिए ठीक है, लेकिन जब मैं तेज़ी से स्क्रॉल करता हूं, तो यह दो बार आग लग जाता है। धीमी स्क्रॉल में कोई समस्या नहीं है। – horse

4
var now = new Date().getTime(); 
$(window).scroll(function() { 
    if (window.pageYOffset > loadMoreButton.offsetTop - 1000) 
    { 
     if (new Date().getTime() - now > 1000) 
     { 
      console.log("Task executed once per second"); 
      now = new Date().getTime(); 
     } 
    } 
}); 

या

आप उपयोग कर सकते हैं थ्रॉटलिंग fonction कॉल: throttling-function-calls

function throttle(fn, threshhold, scope) { 
    threshhold || (threshhold = 250); 
    var last, 
     deferTimer; 
    return function() { 
    var context = scope || this; 

    var now = +new Date, 
     args = arguments; 
    if (last && now < last + threshhold) { 
     // hold on to it 
     clearTimeout(deferTimer); 
     deferTimer = setTimeout(function() { 
     last = now; 
     fn.apply(context, args); 
     }, threshhold); 
    } else { 
     last = now; 
     fn.apply(context, args); 
    } 
    }; 
} 

आप इसे इस तरह कॉल कर सकते हैं:

$('body').on('mousemove', throttle(function (event) { 
    console.log('tick'); 
}, 1000)); 
+2

कृपया इस कोड में कुछ टिप्पणियां और विवरण जोड़ें। –

3

यहाँ एक समाधान है कि नहीं करता है एक extr के उपयोग की आवश्यकता नहीं है एक जेएस लाइब्रेरी या प्लगइन, जिसका उद्देश्य सादगी के लिए है। यह अन्य कार्यान्वयन के रूप में उतना ही कुशल नहीं हो सकता है, लेकिन जब भी आप स्क्रॉल करते हैं तो यह आपके मुख्य कार्यक्रम को फायर करने से निश्चित रूप से एक कदम है।

यह डैनी वान कुटेन द्वारा इस blog post से लिया गया था। जिसे मैंने अपने ब्लॉग पर अपने बैक-टू-टॉप बटन के लिए onscroll() ईवेंट में देरी करने में उपयोग किया है।

var timer; 
$(window).scroll(function() { 
    if(timer) { 
     window.clearTimeout(timer); 
    } 
    timer = window.setTimeout(function() { 
     // actual code here. Your call back function. 
    console.log("Firing!"); 
    }, 100); 
}); 

तुम भी आगे कॉलबैक फ़ंक्शन से बाहर चर बाहर ले जाकर प्रदर्शन में सुधार कर सकते हैं अनावश्यक recalculations जो बदलेगा नहीं $(window).height() या कुछ स्थिर div तत्व की ऊंचाई के मान से बचने के लिए, उदाहरण के लिए एक बार पेज लोड होने ।

यहां एक उदाहरण है जो मेरे उपयोग के मामले से अनुकूलित है।

var scrollHeight = $("#main-element").height(); //never changes, no need to recalculate. 
$(window).on('scroll', function() { 
    if (timer) 
     window.clearTimeout(timer); 
    timer = window.setTimeout(function() { 
     var scrollPosition = $(window).height() + $(window).scrollTop();  
     if ($(window).scrollTop() < 500) 
      $(".toggle").fadeIn(800); 
     else 
      $(".toggle").fadeOut(800); 
    }, 150); //only fire every 150 ms. 
}); 

यह केवल हर 150ms पर अमल, वरना टाइमर 0 वापस करने के लिए रीसेट करता है, तो 150ms पास नहीं किया है करने के लिए वास्तविक समारोह सीमित करता है। आपको जो चाहिए उसे पूरा करने के लिए मूल्य को ट्विक करें।

9

इस स्थिति को हल करने के लिए jQuery के निर्माता जॉन रेसिग से एक शानदार स्पष्टीकरण है।

var outerPane = $details.find(".details-pane-outer"), 
    didScroll = false; 

$(window).scroll(function() { 
    didScroll = true; 
}); 

setInterval(function() { 
    if (didScroll) { 
     didScroll = false; 
     // Check your page position and then 
     // Load in more results 
    } 
}, 250); 

स्रोत: http://ejohn.org/blog/learning-from-twitter/

संबंधित मुद्दे