jQuery – 如何等待“resize”事件的“结束”,然后才执行一个操作?

所以我现在使用类似于:

$(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的代码!

    你可以使用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); }); 

    谢谢Mark!

    Internet Explorer提供了一个resizeEnd事件。 其他浏览器会在调整大小时多次触发resize事件。

    这里还有其他很好的答案,展示了如何使用setTimeout和lodash和下划线中的.throttle , .debounce方法,所以我会提到Ben Alman的油门去抖jQuery插件 ,它可以完成你之后的任务。

    假设你有这个功能,你要触发一个调整大小后:

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

    节流示例
    在下面的例子中,窗口大小调整期间,每250毫秒只调用一次onResize()

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

    防反弹示例
    在以下示例中,仅在窗口调整大小操作结束时调用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

    您可以将引用ID存储到任何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)); }); 

    更新

    我写了一个扩展,以增强jQuery on (& bind )-event处理程序on的默认值。 如果事件在给定时间间隔内未触发,则将一个或多个事件的事件处理函数附加到所选元素。 如果您只想在延迟后触发回调(如调整大小事件),则此功能非常有用。 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)); 

    像任何其他onbind -event处理程序一样使用它,除了可以将最后一个参数传递给另一个参数:

     $(window).on('resize', function(e) { console.log(e.type + '-event was 200ms not triggered'); }, 200); 

    http://jsfiddle.net/ARTsinn/EqqHx/

    一个解决方案是扩展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);

    这是对Dolan上面代码的修改,我添加了一个特性,它在调整大小的开始时检查窗口大小,并将其与调整大小结束时的大小进行比较,如果大小大于或小于边距(例如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'事件。

    没有必要把日期和时间搞砸。

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

    因为选定的答案并没有真正的工作..如果你不使用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”,在500ms之后(或者你的首选项)获得当前的窗口大小,并且比较原始值和当前值,如果它们不相同,那么窗口仍然被重新调整大小。 不要忘记在生产中删除控制台消息,并且(可选)可以使“setFn”自行执行。

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

    这工作为我想在铬做。 这将不会触发回调,直到最后一次调整大小事件后的200毫秒。

    UPDATE!

    更好的替代方案也由我创建在这里: https //stackoverflow.com/a/23692008/2829600 (支持“删除功能”)

    原来的帖子:

    我写了这个简单的函数来处理执行中的延迟,在jQuery .scroll()和.resize()中很有用,所以对于特定的id字符串,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! */ 

    调整窗口的ResizeStartResizeEnd事件

    http://jsfiddle.net/04fLy8t4/

    我实现了在用户DOM元素上触发两个事件的函数:

    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... } 

    Mark Coleman的答案肯定比选择的答案要好得多,但是如果你想避免超时ID的全局变量(Mark的答案中的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); }); 

    我不知道我的代码是为其他人工作的,但是对我来说真的很棒。 我通过分析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); }