jQuery - как дождаться окончания события 'resize' и только потом выполнить действие? - PullRequest
219 голосов
/ 30 марта 2011

Так что я сейчас использую что-то вроде:

$(window).resize(function(){resizedw();});

Но это вызывается много раз, пока продолжается процесс изменения размера. Можно ли поймать событие, когда оно заканчивается?

Ответы [ 23 ]

489 голосов
/ 30 марта 2011

Вы можете использовать setTimeout() и clearTimeout()

function resizedw(){
    // Haven't resized in 100ms!
}

var doit;
window.onresize = function(){
  clearTimeout(doit);
  doit = setTimeout(resizedw, 100);
};

Пример кода на jsfiddle .

161 голосов
/ 08 мая 2011

Мне повезло со следующей рекомендацией: http://forum.jquery.com/topic/the-resizeend-event

Вот код, так что вам не нужно копаться по ссылке и источнику его сообщения:

var rtime;
var timeout = false;
var delta = 200;
$(window).resize(function() {
    rtime = new Date();
    if (timeout === false) {
        timeout = true;
        setTimeout(resizeend, delta);
    }
});

function resizeend() {
    if (new Date() - rtime < delta) {
        setTimeout(resizeend, delta);
    } else {
        timeout = false;
        alert('Done resizing');
    }               
}

Спасибо sime.vidas за код!

73 голосов
/ 13 января 2015

Это код, который я пишу в соответствии с ответом @Mark Coleman:

$(window).resize(function() {
    clearTimeout(window.resizedFinished);
    window.resizedFinished = setTimeout(function(){
        console.log('Resized finished.');
    }, 250);
});

Спасибо, Марк!

34 голосов
/ 30 марта 2011

Internet Explorer предоставляет событие resizeEnd .Другие браузеры будут вызывать событие изменения размера много раз, пока вы изменяете размер.

Здесь есть другие замечательные ответы, которые показывают, как использовать setTimeout и .throttle , .debounce методы от lodash и underscore, поэтому я упомяну плагин Джена Бена Алмана *1014*, который выполняет то, что вам нужно.

Предположим, у вас есть эта функция, которую вы хотите вызвать после изменения размера:

function onResize() {
  console.log("Resize just happened!");
};

Пример газа
В следующем примере onResize() будет вызываться только один раз каждые 250миллисекунды при изменении размера окна.

$(window).resize( $.throttle( 250, onResize) );

Пример отладки
В следующем примере onResize() будет вызываться только один раз в конце действия изменения размера окна.Это достигает того же результата, который @Mark представляет в своем ответе.

$(window).resize( $.debounce( 250, onResize) );
24 голосов
/ 20 июля 2013

Существует элегантное решение, использующее Underscore.js Так что, если вы используете его в своем проекте, вы можете сделать следующее -

$( window ).resize( _.debounce( resizedw, 500 ) );

Это должно бытьдостаточно :) Но, если вам интересно узнать больше об этом, вы можете проверить мой пост в блоге - http://rifatnabi.com/post/detect-end-of-jquery-resize-event-using-underscore-debounce(deadlink)

7 голосов
/ 10 ноября 2016

Одним из решений является расширение jQuery с помощью функции, например: resized

$.fn.resized = function (callback, timeout) {
    $(this).resize(function () {
        var $this = $(this);
        if ($this.data('resizeTimeout')) {
            clearTimeout($this.data('resizeTimeout'));
        }
        $this.data('resizeTimeout', setTimeout(callback, timeout));
    });
};

Пример использования:

$(window).resized(myHandler, 300);

7 голосов
/ 13 июня 2013

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

var loop = setInterval(func, 30);

// some time later clear the interval
clearInterval(loop);

Чтобы сделать это без «глобальной» переменной, вы можете добавить локальную переменную в саму функцию.Пример:

$(window).resize(function() {
    clearTimeout(this.id);
    this.id = setTimeout(doneResizing, 500);
});

function doneResizing(){
  $("body").append("<br/>done!");   
}
3 голосов
/ 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/

2 голосов
/ 19 декабря 2013

Это модификация кода Долана выше, я добавил функцию, которая проверяет размер окна в начале изменения размера и сравнивает его с размером в конце изменения размера, если размер больше или меньше, чемполе (например, 1000) затем перезагружается.

var rtime = new Date(1, 1, 2000, 12,00,00);
var timeout = false;
var delta = 200;
var windowsize = $window.width();
var windowsizeInitial = $window.width();

$(window).on('resize',function() {
    windowsize = $window.width();
    rtime = new Date();
    if (timeout === false) {
            timeout = true;
            setTimeout(resizeend, delta);
        }
});

function resizeend() {
if (new Date() - rtime < delta) {
    setTimeout(resizeend, delta);
    return false;
} else {
        if (windowsizeInitial > 1000 && windowsize > 1000 ) {
            setTimeout(resizeend, delta);
            return false;
        }
        if (windowsizeInitial < 1001 && windowsize < 1001 ) {
            setTimeout(resizeend, delta);
            return false;
        } else {
            timeout = false;
            location.reload();
        }
    }
    windowsizeInitial = $window.width();
    return false;
}
2 голосов
/ 18 марта 2016

Ответ Марка Коулмана, безусловно, намного лучше, чем выбранный ответ, но если вы хотите избежать глобальной переменной для идентификатора тайм-аута (переменная doit в ответе Марка), вы можете выполнить одно из следующих действий:

(1) Используйте выражение для немедленного вызова функции (IIFE) для создания замыкания.

$(window).resize((function() { // This function is immediately invoked
                               // and returns the closure function.
    var timeoutId;
    return function() {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(function() {
            timeoutId = null; // You could leave this line out.
            // Code to execute on resize goes here.
        }, 100);
    };
})());

(2) Используйте свойство функции обработчика событий.

$(window).resize(function() {
    var thisFunction = arguments.callee;
    clearTimeout(thisFunction.timeoutId);
    thisFunction.timeoutId = setTimeout(function() {
        thisFunction.timeoutId = null; // You could leave this line out.
        // Code to execute on resize goes here.
    }, 100);
});
...