jQuery-как дождаться окончания события "resize" и только после этого выполнить действие?



поэтому в настоящее время я использую что-то вроде:



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


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

1124   22  

22 ответов:

Мне повезло со следующей рекомендацией: 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');
    }               
}

спасибо Симе.Видас для кода!

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

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

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

пример кода jsfiddle.

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

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

Спасибо!!

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

есть и другие отличные ответы, которые показывают, как использовать setTimeout и в .дроссель,.дребезга методы лодашь и подчеркивания, поэтому я упомяну дроссель-debounce jQuery плагин которая выполняет то, что вы после.

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

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

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

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

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

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

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

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

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

вы можете сохранить идентификатор ссылки на любой 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!");   
}

одним из решений является расширение 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);

можно использовать 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/

Это модификация кода Долана выше, я добавил функцию, которая проверяет размер окна в начале изменения размера и сравнивает его с размером в конце изменения размера, если размер больше или меньше, чем поле (например. 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;
}

Я написал функцию обертки litte самостоятельно...

onResize  =   function(fn) {
    if(!fn || typeof fn != 'function')
        return 0;

    var args    = Array.prototype.slice.call(arguments, 1);

    onResize.fnArr    = onResize.fnArr || [];
    onResize.fnArr.push([fn, args]);

    onResize.loop   = function() {
        $.each(onResize.fnArr, function(index, fnWithArgs) {
            fnWithArgs[0].apply(undefined, fnWithArgs[1]);
        });
    };

    $(window).on('resize', function(e) {
        window.clearTimeout(onResize.timeout);
        onResize.timeout    = window.setTimeout("onResize.loop();", 300);
    });
};

здесь использование:

var testFn  = function(arg1, arg2) {
    console.log('[testFn] arg1: '+arg1);
    console.log('[testFn] arg2: '+arg2);
};

// document ready
$(function() {
    onResize(testFn, 'argument1', 'argument2');
});
(function(){
    var special = jQuery.event.special,
        uid1 = 'D' + (+new Date()),
        uid2 = 'D' + (+new Date() + 1);

    special.resizestart = {
        setup: function() {
            var timer,
                handler =  function(evt) {
                    var _self = this,
                        _args = arguments;
                    if (timer) {
                        clearTimeout(timer);
                    } else {
                        evt.type = 'resizestart';
                        jQuery.event.handle.apply(_self, _args);
                    }

                    timer = setTimeout( function(){
                        timer = null;
                    }, special.resizestop.latency);
                };
            jQuery(this).bind('resize', handler).data(uid1, handler);
        },
        teardown: function(){
            jQuery(this).unbind( 'resize', jQuery(this).data(uid1) );
        }
    };

    special.resizestop = {
        latency: 200,
        setup: function() {
            var timer,
                handler = function(evt) {
                    var _self = this,
                        _args = arguments;
                    if (timer) {
                        clearTimeout(timer);
                    }
                    timer = setTimeout( function(){
                        timer = null;
                        evt.type = 'resizestop';
                        jQuery.event.handle.apply(_self, _args);
                    }, special.resizestop.latency);
                };

            jQuery(this).bind('resize', handler).data(uid2, handler);
        },
        teardown: function() {
            jQuery(this).unbind( 'resize', jQuery(this).data(uid2) );
        }
    };
})();

$(window).bind('resizestop',function(){
    //...
});

Ну, что касается оконного менеджера, каждое событие изменения размера-это свое собственное сообщение с отличным началом и концом, поэтому технически каждый раз, когда окно изменяется, оно и конец.

сказав, что, может быть, вы хотите установить задержку в продолжении? вот пример.

var t = -1;
function doResize()
{
    document.write('resize');
}
$(document).ready(function(){
    $(window).resize(function(){
        clearTimeout(t);
        t = setTimeout(doResize, 1000);
    });
});

вот очень простой скрипт для запуска события "resizestart" и "resizeend" на объекте окна.

нет необходимости возиться с датами и временем.

The d переменная представляет количество миллисекунд между событиями изменения размера перед запуском события конца изменения размера, вы можете играть с этим, чтобы изменить чувствительность конечного события.

чтобы слушать эти события все, что вам нужно сделать, это:

resizestart: $(window).on('resizestart', function(event){console.log('Resize Start!');});

resizeend: $(window).on('resizeend', function(event){console.log('Resize End!');});

(function ($) {
    var d = 250, t = null, e = null, h, r = false;

    h = function () {
        r = false;
        $(window).trigger('resizeend', e);
    };

    $(window).on('resize', function (event) {
        e = event || e;
        clearTimeout(t);

        if (!r) {
            $(window).trigger('resizestart', e);
            r = true;
        }

        t = setTimeout(h, d);
    });
}(jQuery));

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

(1) использовать сразу же вызывается функция выражения (жизнь), чтобы создать закрытия.

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

так как выбранный ответ на самом деле не работает .. и если вы не используете jquery, вот простая функция дроссельной заслонки с примером того, как ее использовать с изменением размера окна

    function throttle(end,delta) {

    var base = this;

    base.wait = false;
    base.delta = 200;
    base.end = end;

    base.trigger = function(context) {

        //only allow if we aren't waiting for another event
        if ( !base.wait ) {

            //signal we already have a resize event
            base.wait = true;

            //if we are trying to resize and we 
            setTimeout(function() {

                //call the end function
                if(base.end) base.end.call(context);

                //reset the resize trigger
                base.wait = false;
            }, base.delta);
        }
    }
};

var windowResize = new throttle(function() {console.log('throttle resize');},200);

window.onresize = function(event) {
    windowResize.trigger();
}

это сработало для меня, так как я не хотел использовать какие-либо плагины.

$(window).resize(function() {
    var originalWindowSize = 0;
    var currentWidth = 0;

    var setFn = function () {
        originalWindowSize = $(window).width();
    };

    var checkFn = function () {
        setTimeout(function () {
            currentWidth = $(window).width();
            if (currentWidth === originalWindowSize) {
                console.info("same? = yes") 
                // execute code 
            } else {
                console.info("same? = no"); 
                // do nothing 
            }
        }, 500)
    };
    setFn();
    checkFn();
});

при изменении размера окна вызовите "setFn", который получает ширину окна и сохраняет как"originalWindowSize". Затем вызовите "checkFn", который после 500 мс (или вашего предпочтения) получает текущий размер окна и сравнивает оригинал с текущим, если они не совпадают, то окно все еще изменяется. Не забудьте удалить консольные сообщения в производстве, и (необязательно) может сделать "setFn" самоисполняющимся.

var resizeTimer;
$( window ).resize(function() {
    if(resizeTimer){
        clearTimeout(resizeTimer);
    }
    resizeTimer = setTimeout(function() {
        //your code here
        resizeTimer = null;
        }, 200);
    });

это сработало для того, что я пытался сделать в chrome. Это не будет запускать обратный вызов до 200 мс после последнего события изменения размера.

обновление!

лучшая альтернатива также созданная мной здесь: https://stackoverflow.com/a/23692008/2829600 (поддерживает "удалить функции")

ОРИГИНАЛЬНЫЙ ПОСТ:

Я написал эту простую функцию для обработки задержки в выполнении, полезной внутри jQuery .свиток и. resize () поэтому callback_f будет выполняться только один раз для определенной строки идентификатора.

function delay_exec( id, wait_time, callback_f ){

    // IF WAIT TIME IS NOT ENTERED IN FUNCTION CALL,
    // SET IT TO DEFAULT VALUE: 0.5 SECOND
    if( typeof wait_time === "undefined" )
        wait_time = 500;

    // CREATE GLOBAL ARRAY(IF ITS NOT ALREADY CREATED)
    // WHERE WE STORE CURRENTLY RUNNING setTimeout() FUNCTION FOR THIS ID
    if( typeof window['delay_exec'] === "undefined" )
        window['delay_exec'] = [];

    // RESET CURRENTLY RUNNING setTimeout() FUNCTION FOR THIS ID,
    // SO IN THAT WAY WE ARE SURE THAT callback_f WILL RUN ONLY ONE TIME
    // ( ON LATEST CALL ON delay_exec FUNCTION WITH SAME ID  )
    if( typeof window['delay_exec'][id] !== "undefined" )
        clearTimeout( window['delay_exec'][id] );

    // SET NEW TIMEOUT AND EXECUTE callback_f WHEN wait_time EXPIRES,
    // BUT ONLY IF THERE ISNT ANY MORE FUTURE CALLS ( IN wait_time PERIOD )
    // TO delay_exec FUNCTION WITH SAME ID AS CURRENT ONE
    window['delay_exec'][id] = setTimeout( callback_f , wait_time );
}


// USAGE

jQuery(window).resize(function() {

    delay_exec('test1', 1000, function(){
        console.log('1st call to delay "test1" successfully executed!');
    });

    delay_exec('test1', 1000, function(){
        console.log('2nd call to delay "test1" successfully executed!');
    });

    delay_exec('test1', 1000, function(){
        console.log('3rd call to delay "test1" successfully executed!');
    });

    delay_exec('test2', 1000, function(){
        console.log('1st call to delay "test2" successfully executed!');
    });

    delay_exec('test3', 1000, function(){
        console.log('1st call to delay "test3" successfully executed!');
    });

});

/* RESULT
3rd call to delay "test1" successfully executed!
1st call to delay "test2" successfully executed!
1st call to delay "test3" successfully executed!
*/

ResizeStart и ResizeEnd событий для окна

http://jsfiddle.net/04fLy8t4/

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

  1. resizestart
  2. resizeend

код:

var resizeEventsTrigger = (function () {
    function triggerResizeStart($el) {
        $el.trigger('resizestart');
        isStart = !isStart;
    }

    function triggerResizeEnd($el) {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(function () {
            $el.trigger('resizeend');
            isStart = !isStart;
        }, delay);
    }

    var isStart = true;
    var delay = 200;
    var timeoutId;

    return function ($el) {
        isStart ? triggerResizeStart($el) : triggerResizeEnd($el);
    };

})();

$("#my").on('resizestart', function () {
    console.log('resize start');
});
$("#my").on('resizeend', function () {
    console.log('resize end');
});

window.onresize = function () {
    resizeEventsTrigger( $("#my") );
};
var flag=true;
var timeloop;

$(window).resize(function(){
    rtime=new Date();
    if(flag){
        flag=false;
        timeloop=setInterval(function(){
            if(new Date()-rtime>100)
                myAction();
        },100);
    }
})
function myAction(){
    clearInterval(timeloop);
    flag=true;
    //any other code...
}

Я не знаю, это мой код работать для других, но это действительно сделать большую работу для меня. Я получил эту идею, проанализировав код Dolan Antenucci, потому что его версия не работает для меня, и я действительно надеюсь, что это будет полезно кому-то.

var tranStatus = false;
$(window).resizeend(200, function(){
    $(".cat-name, .category").removeAttr("style");
    //clearTimeout(homeResize);
    $("*").one("webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend",function(event) {
      tranStatus = true;
    });
    processResize();
});

function processResize(){
  homeResize = setInterval(function(){
    if(tranStatus===false){
        console.log("not yet");
        $("*").one("webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend",function(event) {
            tranStatus = true;
        }); 
    }else{
        text_height();
        clearInterval(homeResize);
    }
  },200);
}

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

https://github.com/UniWrighte/resizeOnEnd/blob/master/resizeOnEnd.js

        $(window).resize(function(){
            //call to resizeEnd function to execute function on resize end.
    //can be passed as function name or anonymous function
            resizeEnd(function(){



    });

        });

        //global variables for reference outside of interval
        var interval = null;
        var width = $(window).width();
    var numi = 0; //can be removed in production
        function resizeEnd(functionCall){
            //check for null interval
            if(!interval){
                //set to new interval
                interval = setInterval(function(){
        //get width to compare
                    width2 = $(window).width();
        //if stored width equals new width
                    if(width === width2){
                        //clear interval, set to null, and call passed function
                        clearInterval(interval);
                        interval = null; //precaution
                        functionCall();

                    }
        //set width to compare on next interval after half a second
                    width = $(window).width();
                }, 500);

            }else{
                //logging that should be removed in production
                console.log("function call " + numi++ + " and inteval set skipped");

            }

}

Comments

    Ничего не найдено.