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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2854407/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 02:11:45  来源:igfitidea点击:

JavaScript/JQuery: $(window).resize how to fire AFTER the resize is completed?

javascriptjquery

提问by sarah

I'm using JQuery as such:

我正在使用 JQuery:

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

However, it appears that if the person manually resizes their browser windows by dragging the window edge to make it larger/smaller, the .resizeevent above fires multiple times.

但是,似乎如果该人通过拖动窗口边缘使其变大/变小来手动调整浏览器窗口的大小,则.resize上述事件会多次触发。

Question:How to I call a function AFTER the browser window resize completed (so that the event only fires once)?

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

回答by brahn

Here's a modification of CMS's solution that can be called in multiple places in your code:

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

Usage:

用法:

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

CMS's solution is fine if you only call it once, but if you call it multiple times, e.g. if different parts of your code set up separate callbacks to window resizing, then it will fail b/c they share the timervariable.

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

With this modification, you supply a unique id for each callback, and those unique IDs are used to keep all the timeout events separate.

通过此修改,您为每个回调提供一个唯一 ID,这些唯一 ID 用于将所有超时事件分开。

回答by Carlos Martinez T

I prefer to create an event:

我更喜欢创建一个事件:

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

Here is how you create it:

这是您创建它的方法:

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

You could have this in a global javascript file somewhere.

您可以将其放在某个全局 javascript 文件中。

回答by CMS

I use the following function for delaying repeated actions, it will work for your case:

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

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

Usage:

用法:

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

The callback function passed to it, will execute only when the last call to delay has been made after the specified amount of time, otherwise a timer will be reset, I find this useful for other purposes like detecting when the user stopped typing, etc...

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

回答by JT.

Ifyou have Underscore.js installed, you could:

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

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

回答by DusanV

Some of the previously mentioned solutions did not work for me, even though they are of more general usage. Alternatively I've found this onethat did the job on window 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);
    });
});

回答by Irvin Dominin

Many thanks to David Walsh, here is a vanilla version of underscore debounce.

非常感谢 David Walsh,这是一个普通版的下划线去抖动。

Code:

代码:

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

Simple usage:

简单用法:

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

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

Ref: http://davidwalsh.name/javascript-debounce-function

参考:http: //davidwalsh.name/javascript-debounce-function

回答by newint

Actually, as I know, you can't do some actions exactly when resize is off, simply because you don't know future user's actions. But you can assume the time passed between two resize events, so if you wait a little more than this time and no resize is made, you can call your function.
Idea is that we use setTimeoutand it's id in order to save or delete it. For example we know that time between two resize events is 500ms, therefore we will wait 750ms.

实际上,据我所知,当调整大小关闭时,您无法完全执行某些操作,因为您不知道未来用户的操作。但是您可以假设两个调整大小事件之间经过的时间,因此如果您等待的时间比这个时间长一点并且没有调整大小,您可以调用您的函数。
想法是我们使用setTimeout它的id来保存或删除它。例如,我们知道两个调整大小事件之间的时间是 500 毫秒,因此我们将等待 750 毫秒。

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

回答by vishwajit76

It works for me.See this solution - https://alvarotrigo.com/blog/firing-resize-event-only-once-when-resizing-is-finished/

这个对我有用。请参阅此解决方案 - 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 
}

回答by gzzz

Declare globally delayed listener:

声明全局延迟侦听器:

var resize_timeout;

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

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

And below use listeners to resizedevent as you want:

下面根据需要使用侦听器进行resized事件:

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

回答by Déján K??di?

Simple jQuery plugin for delayed window resize event.

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

SYNTAX:

句法:

Add new function to resize event

添加新功能以调整事件大小

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

Remove the function(by declaring its ID) added earlier

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

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

Remove all functions

删除所有功能

jQuery(window).resizeDelayed( false );

USAGE:

用法:

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

USAGE OUTPUT:

使用输出:

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

PLUGIN:

插入:

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

    }

})();