J'utilise donc 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 lorsqu'il se termine?
J'utilise donc 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 lorsqu'il se termine?
Réponses:
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 le lien et la source de son article:
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!
new Date(-1E12)
- c'est-à-dire que JSLint met en garde contre l'utilisation 00
.
rtime: Date; .... if (+new Date() - +rtime < delta)
et dans la fonction de redimensionnement tapuscrit devrait être une fonction flèche comme celle-ci resizeend=()=>
. Parce que dans la fonction resizeend, this
référence à l'objet window.
Vous pouvez utiliser setTimeout()
etclearTimeout()
function resizedw(){
// Haven't resized in 100ms!
}
var doit;
window.onresize = function(){
clearTimeout(doit);
doit = setTimeout(resizedw, 100);
};
Exemple de code sur jsfiddle .
$(document)
, la détection de la souris serait limitée aux utilisateurs exécutant Microsoft Windows et les versions vulnérables de son Internet Explorer: iedataleak.spider.io/demo
Voici 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!
resizeTimer
est une variable globale, ce qui signifie qu'elle est définie non window
, donc c'est exactement la même chose qu'ici, seul cet exemple est meilleur car vous n'avez pas besoin de définir la variable en externe. et il est également judicieux d'ajouter cette variable à l' window
objet, car c'est l'objet auquel l'écouteur d'événements est lié.
Internet Explorer fournit un événement resizeEnd . D'autres navigateurs déclencheront l'événement de redimensionnement plusieurs fois pendant le redimensionnement.
Il y a d'autres bonnes réponses ici qui montrent comment utiliser setTimeout et le .throttle ,Méthodes .debounce de lodash et underscore, donc je mentionnerai le plugin jQuery de throttle-debounce de Ben Alman qui accomplit ce que vous recherchez.
Supposons que vous ayez cette fonction que vous souhaitez déclencher après un redimensionnement:
function onResize() {
console.log("Resize just happened!");
};
Exemple de limitation
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 de debounce
Dans l'exemple suivant, onResize()
ne sera appelé qu'une fois à la fin d'une action de redimensionnement de fenêtre. Cela permet d'obtenir le même résultat que @Mark présente dans sa réponse.
$(window).resize( $.debounce( 250, onResize) );
Il existe une solution élégante utilisant Underscore.js Donc, si vous l'utilisez dans votre projet, vous pouvez faire ce qui suit -
$( window ).resize( _.debounce( resizedw, 500 ) );
Cela devrait suffire :) Mais, si vous êtes intéressé à en savoir plus à ce sujet, vous pouvez consulter mon article de blog - http://rifatnabi.com/post/detect-end-of-jquery-resize-event-using-underscore -debounce (lien mort)
lodash
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);
Vous pouvez stocker un identifiant de référence dans 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!");
}
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 gestionnaire par défaut on
(& bind
) -event de jQuery. Il attache 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é pendant un intervalle donné. Ceci est utile si vous souhaitez déclencher un rappel uniquement après un délai, comme l'événement resize, 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 on
ou bind
-event, sauf que vous pouvez passer un paramètre supplémentaire en dernier:
$(window).on('resize', function(e) {
console.log(e.type + '-event was 200ms not triggered');
}, 200);
Il existe une méthode beaucoup plus simple pour exécuter une fonction à la fin du redimensionnement que de calculer le temps delta entre deux appels, faites-le simplement comme ceci:
var resizeId;
$(window).resize(function() {
clearTimeout(resizeId);
resizeId = setTimeout(resizedEnded, 500);
});
function resizedEnded(){
...
}
Et l'équivalent pour Angular2 :
private resizeId;
@HostListener('window:resize', ['$event'])
onResized(event: Event) {
clearTimeout(this.resizeId);
this.resizeId = setTimeout(() => {
// Your callback method here.
}, 500);
}
Pour la méthode angulaire, utilisez la () => { }
notation dans le setTimeout
pour conserver la portée, sinon vous ne pourrez pas effectuer d'appels de fonction ou utiliser this
.
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 se 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;
}
La réponse de Mark Coleman est certainement bien meilleure que la réponse sélectionnée, mais si vous voulez éviter la variable globale pour l'ID de délai d'attente (le doit
variable dans la réponse de Mark), vous pouvez effectuer l'une des actions suivantes:
(1) Utilisez une expression de fonction immédiatement invoqué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);
});
j'ai écrit une fonction wrapper litte sur mon propre ...
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'utilisation:
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(){
//...
});
Eh bien, pour autant que le gestionnaire de fenêtres est concerné, chaque événement resize est son propre message, avec un début et à la fin distincte, donc techniquement, chaque fois que la fenêtre est redimensionnée, elle est la fin.
Cela dit, vous souhaitez peut-être retarder 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);
});
});
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 fouiner avec les dates et les heures.
La d
variable 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 jouer avec cela pour modifier la sensibilité de l'événement de fin.
Pour écouter ces événements, il vous suffit de:
redémarrer: $(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));
Voici ce que j'utilise pour retarder les actions répétées, il peut être appelé à plusieurs endroits dans 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);
});
puisque la réponse sélectionnée n'a pas vraiment fonctionné .. et si vous n'utilisez pas jquery, voici une fonction de limitation simple avec un exemple de la façon de l'utiliser 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();
}
cela a fonctionné pour moi car je ne voulais pas utiliser de plugins.
$(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();
});
Sur la fenêtre, redimensionnez invoquer "setFn" qui obtient la largeur de la fenêtre et enregistrez-le sous "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 courant, si elles ne sont pas les mêmes, alors la fenêtre est toujours redimensionnée. N'oubliez pas de supprimer les messages de la console en production et (facultatif) peut rendre "setFn" auto-exécutable.
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.
Une meilleure alternative également créée par moi est ici: https://stackoverflow.com/a/23692008/2829600 (prend en charge les "fonctions de suppression")
J'ai écrit cette fonction simple pour gérer le retard d'exécution, utile dans jQuery .scroll () et .resize () Donc callback_f ne fonctionnera qu'une seule fois pour une chaîne d'ID 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!
*/
$(window).resize(function() { delay_exec('test1', 30, function() { ... delayed stuff here ... }); });
:? Code assez propre sinon. Merci d'avoir partagé. :)
J'ai implémenté une fonction qui déclenche deux événements sur l'élément DOM utilisateur:
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") );
};
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...
}
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 Dolan Antenucci parce que sa version ne fonctionne pas pour moi et j'espère vraiment qu'elle 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);
}
J'ai écrit une fonction qui transmet une fonction lorsqu'elle est enveloppé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 d'expiration. Cela lui permet de fonctionner indépendamment de l'événement de redimensionnement autre qu'une entrée de journal qui doit ê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");
}
}
.one()
sorte qu'il ne s'exécute qu'après tout redimensionnement et non pas encore et encore?