[javascript] إطلاق الحدث التمرير عدة مرات. أنا فقط أريدها أن تطلق أقصاها ، على سبيل المثال ، مرة في الثانية


Answers

إحدى الطرق لحل هذه المشكلة هي تحديد فاصل زمني وفقط معالجة حدث تمرير مرة واحدة خلال تلك الفترة الزمنية. إذا جاء أكثر من حدث تمرير واحد أثناء تلك الفترة الزمنية ، فسوف تتجاهله ويعالجه فقط عندما يمر الفاصل الزمني.

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);
    }
});

سيؤدي هذا إلى إطلاق الحدث التمريري الأول على الفور ومن ثم الحصول على حدث التمرير مرة واحدة تقريبًا كل 100 مللي ثانية أثناء نقل شريط التمرير ومن ثم حدث واحد نهائي بعد توقف شريط التمرير. يمكنك ضبط تكرار الحدث عن طريق تغيير الوسيطة إلى setTimeout (ما يتم تعيينه حاليًا على 100).

هناك عرض تجريبي هنا: http://jsfiddle.net/jfriend00/EBEqZ/ الذي تحتاج إليه لفتح إطار وحدة التحكم ، بدء تحريك شريط التمرير في إطار المحتوى ثم مشاهدة وقت كل حدث التمرير في إطار وحدة التحكم التصحيح . في إصداري من Chrome ، يتم تعيينها على أقل مسافة بين 100 مللي ثانية ويبدو أنها تحدث كل 100-200 مللي ثانية.

Question

لدي صفحة مع "التمرير لانهائي". تقوم بحساب الفرق بين نهاية الصفحة والصفحة الحالية وتحميل المزيد من المحتوى إذا كان هذا الاختلاف صغيرًا بما يكفي. الرمز هو مثل هذا الأمر باستخدام jQuery:

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

الآن ، المشكلة هي أنه في كل مرة أقوم بالتمرير ، يتم تشغيل هذا الحدث عدة مرات في التمرير. أود إطلاق النار على الأكثر كل x ملي ثانية. كيف يمكنني ان افعل هذا؟




هنا هو الحل الذي لا يتطلب استخدام مكتبة JS إضافية أو البرنامج المساعد ، التي تهدف إلى البساطة. قد لا يكون بنفس كفاءة التطبيقات الأخرى ، ولكنه بالتأكيد خطوة إلى الأمام من إطلاق الحدث الرئيسي في كل مرة تقوم بالتمرير.

وقد اتخذ هذا من هذا بلوق وظيفة داني فان كوتين. التي استخدمتها في تأجيل أحداث 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);
});

يمكنك أيضًا تحسين الأداء عن طريق نقل المتغيرات خارج وظيفة رد الاتصال لتجنب عمليات إعادة الحساب غير الضرورية ، على سبيل المثال قيمة $(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. قم بتعديل القيمة لتناسب ما تحتاجه.




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);
    }
}



أنت لا تحتاج إلى جزء كبير من التعليمات البرمجية لوظيفة دواسة الخوارق لائقة. الغرض من وظيفة دواسة الوقود هو تقليل موارد المستعرض ، عدم تطبيق الكثير من الحمل الذي تستخدمه أكثر من ذلك. أيضا ، استخداماتي المختلفة للدالات دواسة الوقود تتطلب العديد من الظروف المختلفة لهم. هذه هي قائمة الأشياء التي تحتاج إليها وظيفة الخانق "الجيدة".

  • الحد الأدنى من النفقات العامة.
  • استدعاء دالة فورية إذا كان أكثر من MS فاصل منذ آخر استدعاء.
  • تجنب تنفيذ وظيفة لفترة أخرى MS.
  • تأخير إطلاق الحدث بشكل مفرط بدلاً من إسقاط الحدث تمامًا.
  • تحديث الحدث المتأخر عند الحاجة بحيث لا يصبح "قديمًا".
  • يمنع الإجراء الافتراضي للحدث عندما تتأخر الوظيفة المخنوقة.
  • تكون قادرًا على إزالة وحدة إصغاء المستمع حدث الخانق.

وأعتقد أن وظيفة دواسة الوقود التالية تفي بجميع هذه.

var cachedThrottleFuncs = [],
    minimumInterval = 200; // minimum interval between throttled function calls
function throttle(func, obj, evt) {
    var timeouttype = 0,
        curFunc;
    function lowerTimeoutType(f){
        timeouttype=0;
        if (curFunc !== undefined){
            curFunc();
            curFunc = undefined;
        }
    };
    return cachedThrottleFuncs[ ~(
        ~cachedThrottleFuncs.indexOf(func) || 
        ~(
          cachedThrottleFuncs.push(function(Evt) {
            switch (timeouttype){
                case 0: // Execute immediatly
                    ++timeouttype;
                    func.call(Evt.target, Evt);
                    setTimeout(lowerTimeoutType, minimumInterval);
                    break;
                case 1: // Delayed execute
                    curFunc = func.bind(Evt.target, Evt);
                    Evt.preventDefault();
            }
          }) - 1
        )
    )];
};
function listen(obj, evt, func){
    obj.addEventListener(evt, throttle(func, obj, evt));
};
function mute(obj, evt, func){
    obj.removeEventListener(evt, throttle(func, obj, evt));
}

استخدام المثال:

listen(document.body, 'scroll', function whenbodyscrolls(){
    if (document.body.scrollTop > 400)
        mute(document.body, 'scroll', whenbodyscrolls();
    else
        console.log('Body scrolled!')
});

بدلاً من ذلك ، إذا كنت تحتاج فقط إلى إضافة مستمعين للحدث ، ولا تحتاج إلى إزالة مستمعي الأحداث ، فيمكنك استخدام الإصدار الأبسط التالي.

var minimumInterval = 200; // minimum interval between throttled function calls
function throttle(func, obj, evt) {
    var timeouttype = 0,
        curEvt = null;
    function lowerTimeoutType(f){
        timeouttype=0;
        if (curEvt !== null){
            func(curEvt);
            curEvt = null;
        }
    };
    return function(Evt) {
        switch (timeouttype){
            case 0: // Execute immediately
                ++timeouttype; // increase the timeouttype
                func(Evt);
                // Now, make it so that the timeouttype resets later
                setTimeout(lowerTimeoutType, minimumInterval);
                break;
            case 1: // Delayed execute
                // make it so that when timeouttype expires, your function
                // is called with the freshest event
                curEvt = Evt;
                Evt.preventDefault();
        }
    };
};

بشكل افتراضي ، يؤدي هذا إلى اختناق الدالة إلى استدعاء واحد على الأكثر كل 200ms. لتغيير الفاصل الزمني إلى عدد مختلف من المللي ثانية ، قم ببساطة بتغيير قيمة minimumInterval .






Links



Tags

javascript javascript