JavaScript / JQuery: $(window).redimensionner comment tirer une fois la redimensionnement terminée?

j'utilise JQuery comme tel:

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

cependant, il semble que si la personne redimensionne manuellement les fenêtres de son navigateur en faisant glisser le bord de la fenêtre pour la rendre plus grande/plus petite, l'événement .resize ci-dessus déclenche plusieurs fois.

Question: comment appeler une fonction après la fenêtre du navigateur redimensionner terminé (de sorte que l'événement ne démarre qu'une fois)?

216
demandé sur armstrhb 2010-05-18 07:33:47

13 réponses

voici une modification de la solution CMS qui peut être appelée à plusieurs endroits dans votre code:

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

Utilisation:

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

la solution de CMS est très bien si vous l'appelez seulement une fois, mais si vous l'appelez plusieurs fois, par exemple si différentes parties de votre code mettent en place des callbacks séparés pour le redimensionnement de la fenêtre, alors il échouera b/C ils partagent la variable timer .

avec cette modification, vous fournissez un unique id pour chaque callback, et ces ID uniques sont utilisés pour garder tous les événements de timeout séparés.

294
répondu brahn 2010-12-27 21:28:38

je préfère créer un événement:

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

Voici comment vous le créez:

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

vous pourriez avoir ceci dans un fichier javascript global quelque part.

129
répondu Carlos Martinez T 2013-10-14 09:24:57

j'utilise la fonction suivante pour retarder les actions répétées, cela fonctionnera pour votre cas:

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

Utilisation:

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

la fonction de rappel qui lui est transmise, ne s'exécute que lorsque le dernier appel au delay a été passé après le temps spécifié, sinon un timer sera réinitialisé, je trouve cela utile pour d'autres raisons comme la détection lorsque l'Utilisateur a arrêté de taper, etc...

118
répondu CMS 2010-05-18 03:55:19

Si vous avez le trait de Soulignement.js installé, vous pouvez:

$(window).resize(_.debounce(function(){
    alert("Resized");
},500));
68
répondu JT. 2013-01-15 08:59:13

certaines des solutions mentionnées précédemment n'ont pas fonctionné pour moi, même si elles sont d'usage plus général. Alternativement j'ai trouvé celui-ci qui a fait le travail sur Redimensionner fenêtre:

$(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);
    });
});
17
répondu DusanV 2014-03-18 12:27:34

Merci beaucoup à David Walsh, voici une version vanille de underscore debounce.

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

usage Simple:

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

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

Réf: http://davidwalsh.name/javascript-debounce-function

10
répondu Irvin Dominin 2015-07-23 12:09:58

en fait, comme je le sais, Vous ne pouvez pas faire certaines actions exactement quand redimensionner est désactivé, simplement parce que vous ne connaissez pas les actions du futur utilisateur. Mais on peut penser que le temps écoulé entre deux événements de redimensionnement, donc si vous attendez un peu plus longtemps et pas de redimensionnement est effectué, vous pouvez appeler votre fonction.

L'idée est que nous utilisons setTimeout et c'est id pour le sauvegarder ou le supprimer. Par exemple nous savons que le temps entre deux événements de redimensionnement est de 500ms, donc nous attendrons 750ms.

var a;
$(window).resize(function(){
  clearTimeout(a);
  a = setTimeout(function(){
    // call your function
  },750);
});
5
répondu newint 2015-01-01 18:47:40

Simple plugin jQuery pour cause de retard de la fenêtre de l'événement de redimensionnement.

syntaxe:

ajouter une nouvelle fonction pour redimensionner l'événement

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

supprimer la fonction(en déclarant son ID) ajouté plus tôt

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

supprimer toutes les fonctions

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

SORTIE D'UTILISATION:

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

    }

})();
2
répondu Déján Kőŕdić 2015-02-23 13:03:51

, Déclarent globalement en retard auditeur:

var resize_timeout;

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

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

et ci-dessous utilisez les écouteurs pour resized événement que vous voulez:

$(window).on('resized', function(){
    console.log('resized');
});
2
répondu gzzz 2018-01-14 14:50:23

en supposant que le curseur de la souris devrait retourner au document après redimensionnement de la fenêtre, nous pouvons créer un comportement de rappel avec l'événement onmouseover. N'oubliez pas que cette solution peut ne pas fonctionner pour tactile des écrans comme prévu.

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);
});
1
répondu onur 2012-11-27 20:32:16

ça me va. Voir cette solution - 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 
}
1
répondu vishwajit chauhan 2018-06-14 11:27:18

regardez cet article de CSS-Tricks. Ils font usage d'une fonctionnalité appelée anti-rebond. Il ne s'exécute que lorsque la fenêtre redimensionner s'arrête.

CSS-Tricks Article Link

0
répondu Noki 2016-04-07 08:00:29

C'est ce que j'ai mis en œuvre:

$(window).redimensionner(fonction(){ setTimeout(someFunction, 500)); });

nous pouvons définir [clear the setTimeout][1] si nous nous attendons à redimensionner moins de 500ms

Bonne Chance...

0
répondu Akash 2018-08-08 10:10:01