Поэтому я сейчас использую что-то вроде:
$(window).resize(function(){resizedw();});
Но это вызывается много раз, пока продолжается процесс изменения размера. Можно ли поймать событие, когда оно заканчивается?
Поэтому я сейчас использую что-то вроде:
$(window).resize(function(){resizedw();});
Но это вызывается много раз, пока продолжается процесс изменения размера. Можно ли поймать событие, когда оно заканчивается?
Ответы:
Мне повезло со следующей рекомендацией: 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 за код!
new Date(-1E12)- то есть JSLint предупреждает об использовании 00.
rtime: Date; .... if (+new Date() - +rtime < delta)и в машинописной функции resizeend должна быть функция стрелки как это resizeend=()=>. Потому что в функции resizeend thisссылка на объект окна.
Вы можете использовать setTimeout()иclearTimeout()
function resizedw(){
// Haven't resized in 100ms!
}
var doit;
window.onresize = function(){
clearTimeout(doit);
doit = setTimeout(resizedw, 100);
};
Пример кода на jsfiddle .
$(document), обнаружение мыши будет ограничено пользователями, работающими под управлением Microsoft Windows и уязвимыми версиями его Internet Explorer: iedataleak.spider.io/demo
Это код, который я пишу в соответствии с ответом @Mark Coleman:
$(window).resize(function() {
clearTimeout(window.resizedFinished);
window.resizedFinished = setTimeout(function(){
console.log('Resized finished.');
}, 250);
});
Спасибо Марк!
resizeTimerявляется глобальной переменной, то есть она определена без изменений window, поэтому она точно такая же, как здесь, только этот пример лучше, так как вам не нужно определять переменную извне. и также имеет смысл добавить эту переменную к windowобъекту, поскольку это объект, с которым связан прослушиватель событий.
Internet Explorer предоставляет событие resizeEnd . Другие браузеры будут вызывать событие изменения размера много раз во время изменения размера.
Здесь есть и другие замечательные ответы, которые показывают, как использовать setTimeout и .throttle ,Методы .debounce от lodash и underscore, поэтому я упомяну плагин jQuery Бена Алмана, который выполняет то, что вам нужно.
Предположим, у вас есть эта функция, которую вы хотите вызвать после изменения размера:
function onResize() {
console.log("Resize just happened!");
};
Пример Throttle
В следующем примере onResize()будет вызываться только один раз каждые 250 миллисекунд при изменении размера окна.
$(window).resize( $.throttle( 250, onResize) );
Пример Debounce
В следующем примере onResize()будет вызываться только один раз в конце действия изменения размера окна. Это достигает того же результата, который @Mark представляет в своем ответе.
$(window).resize( $.debounce( 250, onResize) );
Существует элегантное решение с использованием Underscore.js. Итак, если вы используете его в своем проекте, вы можете сделать следующее:
$( window ).resize( _.debounce( resizedw, 500 ) );
Этого должно быть достаточно :) Но, если вы заинтересованы, чтобы узнать больше об этом, вы можете проверить мой блог - http://rifatnabi.com/post/detect-end-of-jquery-resize-event-using-underscore -debounce (мертвая ссылка)
lodash
Одним из решений является расширение 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);
Вы можете сохранить ссылочный идентификатор для любого 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!");
}
Вы можете использовать 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));
});
Обновить
Я написал расширение для улучшения стандартного on(& bind) -event-handler jQuery . Он прикрепляет функцию-обработчик события для одного или нескольких событий к выбранным элементам, если событие не было запущено в течение заданного интервала. Это полезно, если вы хотите запустить обратный вызов только после задержки, например, события изменения размера или в противном случае.
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-event, за исключением того, что вы можете передать дополнительный параметр как последний:
$(window).on('resize', function(e) {
console.log(e.type + '-event was 200ms not triggered');
}, 200);
Существует гораздо более простой способ выполнить функцию в конце изменения размера, чем вычислять время разницы между двумя вызовами, просто сделайте это следующим образом:
var resizeId;
$(window).resize(function() {
clearTimeout(resizeId);
resizeId = setTimeout(resizedEnded, 500);
});
function resizedEnded(){
...
}
И эквивалент для Angular2 :
private resizeId;
@HostListener('window:resize', ['$event'])
onResized(event: Event) {
clearTimeout(this.resizeId);
this.resizeId = setTimeout(() => {
// Your callback method here.
}, 500);
}
Для углового метода используйте () => { }обозначение в, setTimeoutчтобы сохранить область, иначе вы не сможете выполнять какие-либо вызовы функций или использовать this.
Это модификация вышеприведенного кода Долана, я добавил функцию, которая проверяет размер окна в начале изменения размера и сравнивает его с размером в конце изменения размера, если размер больше или меньше поля ( например, 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;
}
Ответ Марка Колемана, безусловно, намного лучше, чем выбранный ответ, но если вы хотите избежать глобальной переменной для идентификатора тайм-аута ( 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);
});
я написал небольшую упаковочную функцию самостоятельно ...
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 на объекте окна.
Нет необходимости возиться с датами и временем.
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));
Это то, что я использую для задержки повторных действий, это может быть вызвано в нескольких местах в вашем коде:
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
Использование:
$(window).resize(function () {
debounce(function() {
//...
}, 500);
});
так как выбранный ответ на самом деле не работает .. и если вы не используете jquery, вот простая функция throttle с примером того, как использовать его с изменением размера окна
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 .scroll () и .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!
*/
$(window).resize(function() { delay_exec('test1', 30, function() { ... delayed stuff here ... }); });? Довольно чистый код в противном случае. Спасибо, что поделился. :)
Я реализовал функцию, которая запускает два события в пользовательском элементе DOM:
Код:
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");
}
}
.one()так что он выполняется только после того, как все изменения размера сделано, а не снова и снова?