JQuery JavaScript /: $(窗口)。调整大小完成后如何发射?

我使用JQuery这样:

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

然而,如果用户通过拖动窗口边缘来手动调整浏览器窗口的大小,上面的.resize事件会触发多次。

问题:我如何在浏览器窗口调整大小完成后调用函数(使事件只触发一次)?

243879 次浏览

我使用以下函数来延迟重复操作,它将适用于您的情况:

var delay = (function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
};
})();

用法:

$(window).resize(function() {
delay(function(){
alert('Resize...');
//...
}, 500);
});

传递给它的回调函数,只会在指定的时间量之后执行最后一次调用延迟,否则计时器将被重置,我发现这对于其他目的很有用,如检测用户何时停止输入等…

以下是CMS解决方案的修改,可以在代码中的多个地方调用:

var waitForFinalEvent = (function () {
var timers = {};
return function (callback, ms, uniqueId) {
if (!uniqueId) {
uniqueId = "Don't call this twice without a uniqueId";
}
if (timers[uniqueId]) {
clearTimeout (timers[uniqueId]);
}
timers[uniqueId] = setTimeout(callback, ms);
};
})();

用法:

$(window).resize(function () {
waitForFinalEvent(function(){
alert('Resize...');
//...
}, 500, "some unique string");
});

CMS的解决方案是好的,如果你只调用它一次,但如果你多次调用它,例如,如果你的代码的不同部分设置了单独的回调窗口调整大小,那么它将失败b/c他们共享timer变量。

通过这种修改,您可以为每个回调提供一个惟一的id,这些惟一id用于将所有超时事件分开。

我喜欢创建一个事件:

$(window).bind('resizeEnd', function() {
//do something, window hasn't changed size in 500ms
});

下面是如何创建它:

 $(window).resize(function() {
if(this.resizeTO) clearTimeout(this.resizeTO);
this.resizeTO = setTimeout(function() {
$(this).trigger('resizeEnd');
}, 500);
});

你可以把它放在某个全局javascript文件中。

假设鼠标光标在窗口调整大小后应该返回到文档,我们可以使用onmouseover事件创建一个类似回调的行为。不要忘记,这个解决方案可能不适用于预期的触摸屏。

var resizeTimer;
var resized = false;
$(window).resize(function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function() {
if(!resized) {
resized = true;
$(document).mouseover(function() {
resized = false;
// do something here
$(this).unbind("mouseover");
})
}
}, 500);
});

如果如果你已经安装了Underscore.js,你可以:

$(window).resize(_.debounce(function(){
alert("Resized");
},500));

前面提到的一些解决方案对我不起作用,尽管它们的用途更广泛。或者,我有找到了这个来完成窗口大小调整的工作:

$(window).bind('resize', function(e){
window.resizeEvt;
$(window).resize(function(){
clearTimeout(window.resizeEvt);
window.resizeEvt = setTimeout(function(){
//code to do after window is resized
}, 250);
});
});

简单的jQuery插件延迟窗口调整事件。

语法:

增加了调整事件大小的新功能

jQuery(window).resizeDelayed( func, delay, id ); // delay and id are optional

删除之前添加的函数(通过声明其ID)

jQuery(window).resizeDelayed( false, id );

删除所有功能

jQuery(window).resizeDelayed( false );

用法:

// ADD SOME FUNCTIONS TO RESIZE EVENT
jQuery(window).resizeDelayed( function(){ console.log( 'first event - should run after 0.4 seconds'); }, 400,  'id-first-event' );
jQuery(window).resizeDelayed( function(){ console.log('second event - should run after 1.5 seconds'); }, 1500, 'id-second-event' );
jQuery(window).resizeDelayed( function(){ console.log( 'third event - should run after 3.0 seconds'); }, 3000, 'id-third-event' );


// LETS DELETE THE SECOND ONE
jQuery(window).resizeDelayed( false, 'id-second-event' );


// LETS ADD ONE WITH AUTOGENERATED ID(THIS COULDNT BE DELETED LATER) AND DEFAULT TIMEOUT (500ms)
jQuery(window).resizeDelayed( function(){ console.log('newest event - should run after 0.5 second'); } );


// LETS CALL RESIZE EVENT MANUALLY MULTIPLE TIMES (OR YOU CAN RESIZE YOUR BROWSER WINDOW) TO SEE WHAT WILL HAPPEN
jQuery(window).resize().resize().resize().resize().resize().resize().resize();

使用输出:

first event - should run after 0.4 seconds
newest event - should run after 0.5 second
third event - should run after 3.0 seconds

插件:

jQuery.fn.resizeDelayed = (function(){


// >>> THIS PART RUNS ONLY ONCE - RIGHT NOW


var rd_funcs = [], rd_counter = 1, foreachResizeFunction = function( func ){ for( var index in rd_funcs ) { func(index); } };


// REGISTER JQUERY RESIZE EVENT HANDLER
jQuery(window).resize(function() {


// SET/RESET TIMEOUT ON EACH REGISTERED FUNCTION
foreachResizeFunction(function(index){


// IF THIS FUNCTION IS MANUALLY DISABLED ( by calling jQuery(window).resizeDelayed(false, 'id') ),
// THEN JUST CONTINUE TO NEXT ONE
if( rd_funcs[index] === false )
return; // CONTINUE;


// IF setTimeout IS ALREADY SET, THAT MEANS THAT WE SHOULD RESET IT BECAUSE ITS CALLED BEFORE DURATION TIME EXPIRES
if( rd_funcs[index].timeout !== false )
clearTimeout( rd_funcs[index].timeout );


// SET NEW TIMEOUT BY RESPECTING DURATION TIME
rd_funcs[index].timeout = setTimeout( rd_funcs[index].func, rd_funcs[index].delay );


});


});


// <<< THIS PART RUNS ONLY ONCE - RIGHT NOW


// RETURN THE FUNCTION WHICH JQUERY SHOULD USE WHEN jQuery(window).resizeDelayed(...) IS CALLED
return function( func_or_false, delay_or_id, id ){


// FIRST PARAM SHOULD BE SET!
if( typeof func_or_false == "undefined" ){


console.log( 'jQuery(window).resizeDelayed(...) REQUIRES AT LEAST 1 PARAMETER!' );
return this; // RETURN JQUERY OBJECT


}


// SHOULD WE DELETE THE EXISTING FUNCTION(S) INSTEAD OF CREATING A NEW ONE?
if( func_or_false == false ){


// DELETE ALL REGISTERED FUNCTIONS?
if( typeof delay_or_id == "undefined" ){


// CLEAR ALL setTimeout's FIRST
foreachResizeFunction(function(index){


if( typeof rd_funcs[index] != "undefined" && rd_funcs[index].timeout !== false )
clearTimeout( rd_funcs[index].timeout );


});


rd_funcs = [];


return this; // RETURN JQUERY OBJECT


}
// DELETE ONLY THE FUNCTION WITH SPECIFIC ID?
else if( typeof rd_funcs[delay_or_id] != "undefined" ){


// CLEAR setTimeout FIRST
if( rd_funcs[delay_or_id].timeout !== false )
clearTimeout( rd_funcs[delay_or_id].timeout );


rd_funcs[delay_or_id] = false;


return this; // RETURN JQUERY OBJECT


}


}


// NOW, FIRST PARAM MUST BE THE FUNCTION
if( typeof func_or_false != "function" )
return this; // RETURN JQUERY OBJECT


// SET THE DEFAULT DELAY TIME IF ITS NOT ALREADY SET
if( typeof delay_or_id == "undefined" || isNaN(delay_or_id) )
delay_or_id = 500;


// SET THE DEFAULT ID IF ITS NOT ALREADY SET
if( typeof id == "undefined" )
id = rd_counter;


// ADD NEW FUNCTION TO RESIZE EVENT
rd_funcs[id] = {
func : func_or_false,
delay: delay_or_id,
timeout : false
};


rd_counter++;


return this; // RETURN JQUERY OBJECT


}


})();
实际上,据我所知,当resize关闭时,您不能准确地执行某些操作,因为您不知道未来用户的操作。但是您可以假设两次调整大小事件之间的时间间隔,因此如果您等待的时间比这个时间稍长,并且没有进行调整大小,则可以调用您的函数。
我们使用setTimeout和它的id来保存或删除它。例如,我们知道两次调整大小事件之间的时间是500ms,因此我们将等待750ms

.
var a;
$(window).resize(function(){
clearTimeout(a);
a = setTimeout(function(){
// call your function
},750);
});

非常感谢大卫沃尔什,这里是一个香草版本的下划线debounce。

代码:

// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
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);
};
};

简单的用法:

var myEfficientFn = debounce(function() {
// All the taxing stuff you do
}, 250);


$(window).on('resize', myEfficientFn);

裁判:http://davidwalsh.name/javascript-debounce-function

这对我有用。 参见这个解决方案- https://alvarotrigo.com/blog/firing-resize-event-only-once-when-resizing-is-finished/

var resizeId;
$(window).resize(function() {
clearTimeout(resizeId);
resizeId = setTimeout(doneResizing, 500);
});
function doneResizing(){
//whatever we want to do
}

声明全局延迟侦听器:

var resize_timeout;


$(window).on('resize orientationchange', function(){
clearTimeout(resize_timeout);


resize_timeout = setTimeout(function(){
$(window).trigger('resized');
}, 250);
});

下面你可以根据需要使用resized事件的监听器:

$(window).on('resized', function(){
console.log('resized');
});

这是我实现的:

< p > $(窗口).resize(函数(){ setTimeout (someFunction, 500); }); < / p >

如果我们期望resize小于500ms,我们可以清除setTimeout

祝你好运…

许多解决方案。我尝试在mouuseevent之后执行事件,所以我在ouse进入窗口后添加了重载:

jQuery(window).resize(function() {
// this. is window
if(  this.resizeTO) {
clearTimeout(this.resizeTO)
};
    

this.resizeTO = setTimeout(function() {
            

jQuery(window).mouseenter(function() {
if( jQuery(window).width() < 700 &&   jQuery(window).width() > 400 ){
console.log("mouseenter  reloads elements");
// is loading the page
location.reload();
//
}; // just mobile
}); // mouse  fired
}, 400);  // set Time Ouuut
});