JavaScript / JQuery:$(window).resize如何在resize完成后触发?

我正在使用JQuery:

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

但是,如果人员通过拖动窗口边界来手动调整浏览器窗口的大小,上面的.resize事件会多次触发。

问题:如何在浏览器窗口resize完成之后调用函数(以便事件只触发一次)?

以下是可以在代码中的多个位置调用的CMS解决scheme的修改:

 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的解决scheme是好的,但是如果你多次调用它,例如,如果你的代码的不同部分设置单独的callback窗口resize,那么它将失败共享timervariables的B / C。

通过这种修改,您可以为每个callback提供一个唯一的ID,并使用这些唯一的ID来将所有超时事件分开。

我更喜欢创build一个事件:

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

这里是你如何创build它:

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

你可以在一个全球性的JavaScript文件中的某处。

我使用下面的函数来延迟重复的动作,它会适用于你的情况:

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

用法:

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

传递给它的callback函数只有在最后一次延迟调用已经超过指定的时间后才会执行,否则计时器将被重置,我发现这对其他目的有用,比如检测用户何时停止input等等。 ..

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

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

前面提到的一些解决scheme对我来说不起作用,即使它们具有更普遍的用法。 或者我发现这个在窗口resize的工作:

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

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

码:

 // 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

看到这个答案: JavaScript resize事件触发多次,同时拖动resize手柄

它涉及使用超时来延迟执行你的函数。

实际上,据我所知,当resizeclosures时,您无法完全执行某些操作,只是因为您不了解将来的用户操作。 但是,您可以假定在两个resize事件之间经过的时间,所以如果您等待一段时间,并且没有resize,则可以调用您的函数。
想法是我们使用setTimeout并且它是id为了保存或删除它。 例如,我们知道两次resize事件之间的时间是500毫秒,因此我们将等待750毫秒。

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

简单的jQuery插件,用于延迟窗口大小调整事件。

句法:

添加新的function来调整事件大小

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

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

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

删除所有function

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

假设在调整窗口大小后鼠标光标应该返回到文档,我们可以用onmouseover事件创build一个类似callback的行为。 不要忘记,这种解决scheme可能无法按预期的方式启用触摸屏。

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

它为我工作。 看到这个解决scheme – https://alvarotrigo.com/blog/firing-resize-event-only-once-when-resizing-is-finished/

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

看看这个CSS-Tricks文章。 他们利用了一个叫debounce的function。 它只在窗口大小停止时执行。

CSS技巧文章链接