JQuery: Как вызвать событие RESIZE только после его завершения? - PullRequest
109 голосов
/ 28 ноября 2010

Как вызвать функцию после того, как в окнах браузера завершено изменение размера?

Я пытаюсь сделать это так, но у меня проблемы. Я использую функцию события JQuery Resize:

$(window).resize(function() {
  ... // how to call only once the browser has FINISHED resizing?
});

Однако эта функция называется постоянно , если пользователь вручную изменяет размер окна браузера. Это означает, что она может вызывать эту функцию десятки раз за короткий промежуток времени.

Как я могу вызвать функцию изменения размера только один раз (после изменения размера окна браузера)?

UPDATE

Также без использования глобальной переменной.

Ответы [ 8 ]

129 голосов
/ 28 ноября 2010

Вот пример использования инструкций thejh

Вы можете сохранить ссылочный идентификатор для любого setInterval или setTimeout. Как это:

var loop = setInterval(func, 30);

// some time later clear the interval
clearInterval(loop);
85 голосов
/ 28 ноября 2010

Debounce .

function debouncer( func , timeout ) {
   var timeoutID , timeout = timeout || 200;
   return function () {
      var scope = this , args = arguments;
      clearTimeout( timeoutID );
      timeoutID = setTimeout( function () {
          func.apply( scope , Array.prototype.slice.call( args ) );
      } , timeout );
   }
}


$( window ).resize( debouncer( function ( e ) {
    // do stuff 
} ) );

Обратите внимание, этот метод можно использовать для всего, что вы хотите отменить (ключевые события и т. Д.).

Настройте параметр времени ожидания дляоптимальный желаемый эффект.

21 голосов
/ 02 марта 2013

Вы можете использовать setTimeout() и clearTimeout() в сочетании с jQuery.data:

$(window).resize(function() {
    clearTimeout($.data(this, 'resizeTimer'));
    $.data(this, 'resizeTimer', setTimeout(function() {
        //do something
        alert("Haven't resized in 200ms!");
    }, 200));
});

Обновление

Я написал расширение для улучшения jQuery по умолчанию on (& bind) - обработчик событий. Он присоединяет функцию обработчика событий для одного или нескольких событий к выбранным элементам, если событие не было инициировано в течение заданного интервала. Это полезно, если вы хотите запустить обратный вызов только после задержки, например, события изменения размера или в противном случае. https://github.com/yckart/jquery.unevent.js

;(function ($) {
    var methods = { on: $.fn.on, bind: $.fn.bind };
    $.each(methods, function(k){
        $.fn[k] = function () {
            var args = [].slice.call(arguments),
                delay = args.pop(),
                fn = args.pop(),
                timer;

            args.push(function () {
                var self = this,
                    arg = arguments;
                clearTimeout(timer);
                timer = setTimeout(function(){
                    fn.apply(self, [].slice.call(arg));
                }, delay);
            });

            return methods[k].apply(this, isNaN(delay) ? arguments : args);
        };
    });
}(jQuery));

Используйте его как любой другой обработчик события on или bind, за исключением того, что вы можете передать дополнительный параметр как последний:

$(window).on('resize', function(e) {
    console.log(e.type + '-event was 200ms not triggered');
}, 200);

http://jsfiddle.net/ARTsinn/EqqHx/

7 голосов
/ 29 мая 2013

Просто, чтобы добавить к вышесказанному, часто получают нежелательные события изменения размера из-за появления и исчезновения полос прокрутки, вот некоторый код, чтобы избежать этого:

function registerResize(f) {
    $(window).resize(function() {
        clearTimeout(this.resizeTimeout);
        this.resizeTimeout = setTimeout(function() {
            var oldOverflow = document.body.style.overflow;
            document.body.style.overflow = "hidden";
            var currHeight = $(window).height(),
                currWidth = $(window).width();
            document.body.style.overflow = oldOverflow;

            var prevUndefined = (typeof this.prevHeight === 'undefined' || typeof this.prevWidth === 'undefined');
            if (prevUndefined || this.prevHeight !== currHeight || this.prevWidth !== currWidth) {
                //console.log('Window size ' + (prevUndefined ? '' : this.prevHeight + "," + this.prevWidth) + " -> " + currHeight + "," + currWidth);
                this.prevHeight = currHeight;
                this.prevWidth = currWidth;

                f(currHeight, currWidth);
            }
        }, 200);
    });
    $(window).resize(); // initialize
}

registerResize(function(height, width) {
    // this will be called only once per resize regardless of scrollbars changes
});

см. jsfiddle

7 голосов
/ 07 марта 2012
var lightbox_resize = false;
$(window).resize(function() {
    console.log(true);
    if (lightbox_resize)
        clearTimeout(lightbox_resize);
    lightbox_resize = setTimeout(function() {
        console.log('resize');
    }, 500);
});
5 голосов
/ 21 октября 2013

Underscore.js имеет несколько отличных методов для этой задачи: throttle и debounce. Даже если вы не используете Underscore, взгляните на источник этих функций. Вот пример:

var redraw = function() {'redraw logic here'};
var debouncedRedraw = _.debounce(redraw, 750);
$(window).on('resize', debouncedRedraw);
2 голосов
/ 30 июля 2015

Это мой подход:

document.addEventListener('DOMContentLoaded', function(){
    var tos = {};
    var idi = 0;
    var fn  = function(id)
    {
        var len = Object.keys(tos).length;

        if(len == 0)
            return;

        to = tos[id];
        delete tos[id];

        if(len-1 == 0)
            console.log('Resize finished trigger');
    };

    window.addEventListener('resize', function(){
        idi++;
        var id = 'id-'+idi;
        tos[id] = window.setTimeout(function(){fn(id)}, 500);
    });
});

Прослушиватель события изменения размера перехватывает все входящие вызовы изменения размера, создает функцию тайм-аута для каждого и сохраняет идентификатор тайм-аута вместе с итерационным числом, которому предшествует 'id-' (для использования в качестве ключа массива) в tos -array.

каждый раз, когда срабатывает тайм-аут, он вызывает функцию fn, которая проверяет, был ли это последний тайм-аут в массиве tos (функция fn удаляет каждый выполненный тайм-аут). если true (= if(len-1 == 0)), изменение размера завершено.

1 голос
/ 27 февраля 2016

jQuery предоставляет метод off для удаления обработчика событий

$(window).resize(function(){
    if(magic == true) {
        $(window).off('resize', arguments.callee);
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...