web-dev-qa-db-fra.com

Comment attendre la 'fin' de l'événement 'redimensionner' et ensuite seulement effectuer une action?

Donc, j'utilise actuellement quelque chose comme:

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

Mais cela est appelé plusieurs fois pendant le processus de redimensionnement. Est-il possible d'attraper un événement à la fin?

220
Rella

J'ai eu de la chance avec la recommandation suivante: http://forum.jquery.com/topic/the-resizeend-event

Voici le code pour que vous n'ayez pas à fouiller dans le lien et la source de son message:

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

Merci sime.vidas pour le code!

162
Dolan Antenucci

Vous pouvez utiliser setTimeout() et clearTimeout()

function resizedw(){
    // Haven't resized in 100ms!
}

var doit;
window.onresize = function(){
  clearTimeout(doit);
  doit = setTimeout(resizedw, 100);
};

Exemple de code sur jsfiddle .

491
Mark Coleman

Ceci est le code que j'écris selon la réponse de @Mark Coleman:

$(window).resize(function() {
    clearTimeout(window.resizedFinished);
    window.resizedFinished = setTimeout(function(){
        console.log('Resized finished.');
    }, 250);
});

Merci Mark!

74
Roy Shoa

Internet Explorer fournit un événement resizeEnd . D'autres navigateurs déclenchent l'événement de redimensionnement plusieurs fois pendant le redimensionnement.

Il existe d’autres bonnes réponses ici qui montrent comment utiliser setTimeout et les méthodes . Throttle , . Debounce de lodash et de soulignement , je mentionnerai donc Ben Alman plugin jQuery throttle-debounce qui accomplit ce que vous recherchez.

Supposons que vous ayez cette fonction à déclencher après un redimensionnement:

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

Exemple de papillon
Dans l'exemple suivant, onResize() ne sera appelé qu'une fois toutes les 250 millisecondes pendant le redimensionnement d'une fenêtre.

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

Exemple anti-rebond
Dans l'exemple suivant, onResize() ne sera appelé qu'une fois à la fin d'une action de redimensionnement de la fenêtre. Cela donne le même résultat que @Mark présente dans sa réponse.

$(window).resize( $.debounce( 250, onResize) );
34
jessegavin

Il existe une solution élégante utilisant le nderscore.js Ainsi, si vous l’utilisez dans votre projet, vous pouvez effectuer les opérations suivantes:

$( window ).resize( _.debounce( resizedw, 500 ) );

Cela devrait suffire :) Mais, si vous êtes intéressé à en savoir plus à ce sujet, vous pouvez consulter mon blog - http://rifatnabi.com/post/detect-end-of-jquery-resize-event-using-underscore-debounce(lien mort)

24
Rifat

Vous pouvez stocker un identifiant de référence pour n’importe quel setInterval ou setTimeout. Comme ça:

var loop = setInterval(func, 30);

// some time later clear the interval
clearInterval(loop);

Pour ce faire sans variable "globale", vous pouvez ajouter une variable locale à la fonction elle-même. Ex:

$(window).resize(function() {
    clearTimeout(this.id);
    this.id = setTimeout(doneResizing, 500);
});

function doneResizing(){
  $("body").append("<br/>done!");   
}
7
Xman Classical

Une solution consiste à étendre jQuery avec une fonction, par exemple: 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));
    });
};

Exemple d'utilisation:

$(window).resized(myHandler, 300);

7
Jone Polvora

Vous pouvez utiliser setTimeout() et clearTimeout() conjointement avec jQuery.data :

_$(window).resize(function() {
    clearTimeout($.data(this, 'resizeTimer'));
    $.data(this, 'resizeTimer', setTimeout(function() {
        //do something
        alert("Haven't resized in 200ms!");
    }, 200));
});
_

Mettre à jour

J'ai écrit une extension pour améliorer le comportement par défaut de jQuery on (& bind) - gestionnaire d'événements. Il associe une fonction de gestionnaire d'événements pour un ou plusieurs événements aux éléments sélectionnés si l'événement n'a pas été déclenché pour un intervalle donné. Ceci est utile si vous souhaitez déclencher un rappel uniquement après un délai, comme l'événement de redimensionnement, ou autre. 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));
_

Utilisez-le comme n'importe quel autre gestionnaire d'événements on ou bind-, sauf que vous pouvez transmettre un paramètre supplémentaire en dernier:

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

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

3
yckart

La réponse de Mark Coleman est certainement bien meilleure que la réponse sélectionnée, mais si vous souhaitez éviter la variable globale pour l'ID de délai d'attente (la variable doit de la réponse de Mark), vous pouvez effectuer l'une des opérations suivantes:

(1) Utilisez une expression de fonction immédiatement appelée (IIFE) pour créer une fermeture.

$(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) Utilisez une propriété de la fonction de gestionnaire d'événements.

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

Ceci est une modification du code de Dolan ci-dessus, j'ai ajouté une fonctionnalité qui vérifie la taille de la fenêtre au début du redimensionnement et la compare à la taille à la fin du redimensionnement, si la taille est plus grande ou plus petite que la marge ( par exemple 1000) puis il recharge.

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;
}
2
Sami A.

j'ai écrit une petite fonction wrapper moi-même ...

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

Voici l'usage:

var testFn  = function(arg1, arg2) {
    console.log('[testFn] arg1: '+arg1);
    console.log('[testFn] arg2: '+arg2);
};

// document ready
$(function() {
    onResize(testFn, 'argument1', 'argument2');
});
1
user2123506

Voici un script TRÈS simple pour déclencher à la fois un événement 'resizestart' et 'resizeend' sur l'objet window.

Il n'est pas nécessaire de perdre du temps avec les dates et les heures.

La variable d représente le nombre de millisecondes entre les événements de redimensionnement avant de déclencher l'événement de fin de redimensionnement. Vous pouvez utiliser cette variable pour modifier le niveau de sensibilité de l'événement de fin.

Pour écouter ces événements, il vous suffit de:

resizestart: $(window).on('resizestart', function(event){console.log('Resize Start!');});

redimensionner: $(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));
1
Neaox

En ce qui concerne le gestionnaire de fenêtres, chaque événement de redimensionnement est son propre message, avec un début et une fin distincts. Donc techniquement, chaque fois que la fenêtre est redimensionnée, il est la fin.

Cela dit, vous souhaitez peut-être fixer un délai à votre poursuite? Voici un exemple.

var t = -1;
function doResize()
{
    document.write('resize');
}
$(document).ready(function(){
    $(window).resize(function(){
        clearTimeout(t);
        t = setTimeout(doResize, 1000);
    });
});
1
Demian Brecht
(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(){
    //...
});
1
lazer

Je ne sais pas si mon code fonctionne pour d’autres, mais c’est vraiment un excellent travail pour moi. J'ai eu cette idée en analysant le code de Dolan Antenucci parce que sa version ne fonctionne pas pour moi et j'espère vraiment que cela sera utile à quelqu'un.

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);
}
0
Sai Pone Tha Aung

cela a fonctionné pour moi car je ne voulais utiliser aucun plugin.

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

Lors du redimensionnement de la fenêtre, appelez "setFn" qui obtient la largeur de la fenêtre et enregistre sous le nom "originalWindowSize". Ensuite, appelez "checkFn" qui après 500 ms (ou votre préférence) obtient la taille de la fenêtre actuelle et compare l'original au texte actuel. S'ils ne sont pas identiques, la fenêtre est toujours en cours de redimensionnement. N'oubliez pas de supprimer les messages de la console en production et (optionnel) peut rendre "setFn" automatique.

0
Byron Wong

J'ai écrit une fonction qui passe à une fonction lorsqu'elle est encapsulée dans un événement de redimensionnement. Il utilise un intervalle pour que le redimensionnement ne crée même pas constamment des événements de délai d'expiration. Cela lui permet de fonctionner indépendamment de l'événement de redimensionnement autre qu'une entrée de journal qui devrait être supprimée en production.

https://github.com/UniWrighte/resizeOnEnd/blob/master/resizeOnEnd.js

        $(window).resize(function(){
            //call to resizeEnd function to execute function on resize end.
    //can be passed as function name or anonymous function
            resizeEnd(function(){



    });

        });

        //global variables for reference outside of interval
        var interval = null;
        var width = $(window).width();
    var numi = 0; //can be removed in production
        function resizeEnd(functionCall){
            //check for null interval
            if(!interval){
                //set to new interval
                interval = setInterval(function(){
        //get width to compare
                    width2 = $(window).width();
        //if stored width equals new width
                    if(width === width2){
                        //clear interval, set to null, and call passed function
                        clearInterval(interval);
                        interval = null; //precaution
                        functionCall();

                    }
        //set width to compare on next interval after half a second
                    width = $(window).width();
                }, 500);

            }else{
                //logging that should be removed in production
                console.log("function call " + numi++ + " and inteval set skipped");

            }

}

0
David Kamer

puisque la réponse sélectionnée ne fonctionnait pas réellement .. et si vous n'utilisez pas jquery, voici une simple fonction de commande avec un exemple d'utilisation de cette fonction avec le redimensionnement de la fenêtre

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

C’est ce que j’utilise pour retarder les actions répétées, il peut être appelé à plusieurs endroits de votre code:

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:

$(window).resize(function () { 
   debounce(function() {
          //...
    }, 500);
});
0
Hil
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...
}
0
babak iran

événements ResizeStart et ResizeEnd pour la fenêtre

http://jsfiddle.net/04fLy8t4/

J'ai implémenté une fonction qui déclenche deux événements sur l'élément DOM de l'utilisateur:

  1. resizestart
  2. resizeend

Code:

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") );
};
0
WebBrother

MISE À JOUR!

Une meilleure alternative également créée par moi est ici: https://stackoverflow.com/a/23692008/28296 (prend en charge " supprimer des fonctions ")

POSTE ORIGINAL:

J'ai écrit cette fonction simple pour gérer le retard d'exécution, utile dans jQuery .scroll () et .resize (). Callback_f ne s'exécutera qu'une fois pour une chaîne d'identifiant spécifique.

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!
*/
0
Déján Kőŕdić
var resizeTimer;
$( window ).resize(function() {
    if(resizeTimer){
        clearTimeout(resizeTimer);
    }
    resizeTimer = setTimeout(function() {
        //your code here
        resizeTimer = null;
        }, 200);
    });

Cela a fonctionné pour ce que j'essayais de faire en chrome. Cela ne déclenchera le rappel que 200 ms après le dernier événement de redimensionnement.

0
frost287