Quindi attualmente uso qualcosa del tipo:
$(window).resize(function(){resizedw();});
Ma questo viene chiamato molte volte mentre il processo di ridimensionamento continua. È possibile prendere un evento quando finisce?
Quindi attualmente uso qualcosa del tipo:
$(window).resize(function(){resizedw();});
Ma questo viene chiamato molte volte mentre il processo di ridimensionamento continua. È possibile prendere un evento quando finisce?
Risposte:
Ho avuto fortuna con la seguente raccomandazione: http://forum.jquery.com/topic/the-resizeend-event
Ecco il codice in modo da non dover scavare attraverso il link e la fonte del suo post:
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');
}
}
Grazie sime.vidas per il codice!
new Date(-1E12)
- cioè JSLint mette in guardia sull'uso 00
.
rtime: Date; .... if (+new Date() - +rtime < delta)
e in dattiloscritto la funzione di ridimensionamento dovrebbe essere la funzione freccia in questo modo resizeend=()=>
. Perché nella funzione resizeend, this
riferimento all'oggetto finestra.
Puoi usare setTimeout()
eclearTimeout()
function resizedw(){
// Haven't resized in 100ms!
}
var doit;
window.onresize = function(){
clearTimeout(doit);
doit = setTimeout(resizedw, 100);
};
Esempio di codice su jsfiddle .
$(document)
, il rilevamento del mouse sarebbe limitato agli utenti che eseguono Microsoft Windows e alle versioni vulnerabili del suo Internet Explorer: iedataleak.spider.io/demo
Questo è il codice che scrivo in base alla risposta di @Mark Coleman:
$(window).resize(function() {
clearTimeout(window.resizedFinished);
window.resizedFinished = setTimeout(function(){
console.log('Resized finished.');
}, 250);
});
Grazie Marco!
resizeTimer
è una variabile globale, il che significa che non è definita window
, quindi è esattamente la stessa di qui, solo questo esempio è migliore poiché non è necessario definire la variabile esternamente. e ha anche senso aggiungere questa variabile window
all'oggetto poiché è l'oggetto a cui è associato il listener di eventi.
Internet Explorer fornisce un evento resizeEnd . Altri browser attiveranno l'evento di ridimensionamento molte volte durante il ridimensionamento.
Ci sono altre grandi risposte qui che mostrano come usare setTimeout e .throttle ,.debounce da lodash e underscore, quindi menzionerò il plug-in jQuery di throttle-debounce di Ben Alman che realizza ciò che stai cercando .
Supponiamo di avere questa funzione che si desidera attivare dopo un ridimensionamento:
function onResize() {
console.log("Resize just happened!");
};
Esempio di acceleratore Nell'esempio
seguente, onResize()
verrà chiamato solo una volta ogni 250 millisecondi durante un ridimensionamento della finestra.
$(window).resize( $.throttle( 250, onResize) );
Esempio di rimbalzo Nell'esempio
seguente, onResize()
verrà chiamato una sola volta al termine di un'azione di ridimensionamento della finestra. Ciò ottiene lo stesso risultato che @Mark presenta nella sua risposta.
$(window).resize( $.debounce( 250, onResize) );
C'è una soluzione elegante usando il Underscore.js Quindi, se la stai usando nel tuo progetto, puoi fare quanto segue:
$( window ).resize( _.debounce( resizedw, 500 ) );
Questo dovrebbe bastare :) Ma, se sei interessato a saperne di più, puoi controllare il mio post sul blog - http://rifatnabi.com/post/detect-end-of-jquery-resize-event-using-underscore -debounce (deadlink)
lodash
Una soluzione è estendere jQuery con una funzione, ad esempio: 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));
});
};
Esempio di utilizzo:
$(window).resized(myHandler, 300);
È possibile memorizzare un ID di riferimento su qualsiasi setInterval o setTimeout. Come questo:
var loop = setInterval(func, 30);
// some time later clear the interval
clearInterval(loop);
Per fare ciò senza una variabile "globale" è possibile aggiungere una variabile locale alla funzione stessa. Ex:
$(window).resize(function() {
clearTimeout(this.id);
this.id = setTimeout(doneResizing, 500);
});
function doneResizing(){
$("body").append("<br/>done!");
}
Puoi usare setTimeout()
e clearTimeout()
in combinazione con jQuery.data
:
$(window).resize(function() {
clearTimeout($.data(this, 'resizeTimer'));
$.data(this, 'resizeTimer', setTimeout(function() {
//do something
alert("Haven't resized in 200ms!");
}, 200));
});
Aggiornare
Ho scritto un'estensione per migliorare il gestore predefinito on
(& bind
) di jQuery . Associa una funzione del gestore eventi per uno o più eventi agli elementi selezionati se l'evento non è stato attivato per un determinato intervallo. Ciò è utile se si desidera attivare un callback solo dopo un ritardo, ad esempio l'evento di ridimensionamento, oppure.
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));
Usalo come qualsiasi altro gestore on
o bind
-event, tranne che puoi passare un parametro aggiuntivo come ultimo:
$(window).on('resize', function(e) {
console.log(e.type + '-event was 200ms not triggered');
}, 200);
Esiste un metodo molto più semplice per eseguire una funzione alla fine del ridimensionamento rispetto al calcolo del tempo delta tra due chiamate, semplicemente farlo in questo modo:
var resizeId;
$(window).resize(function() {
clearTimeout(resizeId);
resizeId = setTimeout(resizedEnded, 500);
});
function resizedEnded(){
...
}
E l'equivalente per Angular2 :
private resizeId;
@HostListener('window:resize', ['$event'])
onResized(event: Event) {
clearTimeout(this.resizeId);
this.resizeId = setTimeout(() => {
// Your callback method here.
}, 500);
}
Per il metodo angolare, utilizzare la () => { }
notazione in setTimeout
per preservare l'ambito, altrimenti non sarà possibile effettuare chiamate o utilizzare alcuna funzione this
.
Questa è una modifica al codice di Dolan sopra, ho aggiunto una funzione che controlla la dimensione della finestra all'inizio del ridimensionamento e la confronta con la dimensione alla fine del ridimensionamento, se la dimensione è maggiore o minore del margine ( es. 1000) quindi si ricarica.
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 risposta di Mark Coleman è sicuramente molto migliore della risposta selezionata, ma se si desidera evitare la variabile globale per l'ID timeout (il doit
variabile nella risposta di Mark), è possibile effettuare una delle seguenti operazioni:
(1) Utilizzare un'espressione di funzione immediatamente invocata (IIFE) per creare una chiusura.
$(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) Utilizzare una proprietà della funzione del gestore eventi.
$(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);
});
ho scritto una funzione wrapper litte per conto mio ...
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);
});
};
Ecco l'uso:
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(){
//...
});
Bene, per quanto riguarda il gestore delle finestre, ogni evento di ridimensionamento è il suo messaggio, con un inizio e una fine distinti, quindi tecnicamente, ogni volta che la finestra viene ridimensionata, è la fine.
Detto questo, forse vuoi ritardare la tua continuazione? Ecco un esempio
var t = -1;
function doResize()
{
document.write('resize');
}
$(document).ready(function(){
$(window).resize(function(){
clearTimeout(t);
t = setTimeout(doResize, 1000);
});
});
Ecco uno script MOLTO semplice per attivare un evento "resizestart" e "resizeend" sull'oggetto finestra.
Non c'è bisogno di perdere tempo con date e orari.
La d
variabile rappresenta il numero di millisecondi tra gli eventi di ridimensionamento prima di attivare l'evento di fine del ridimensionamento, puoi giocare con questo per cambiare la sensibilità dell'evento di fine.
Per ascoltare questi eventi tutto ciò che devi fare è:
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));
Questo è ciò che uso per ritardare azioni ripetute, può essere chiamato in più punti del codice:
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);
};
};
Uso:
$(window).resize(function () {
debounce(function() {
//...
}, 500);
});
poiché la risposta selezionata in realtà non ha funzionato .. e se non stai usando jquery ecco una semplice funzione dell'acceleratore con un esempio di come usarlo con il ridimensionamento della finestra
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();
}
questo ha funzionato per me in quanto non volevo usare alcun 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();
});
Nella finestra di ridimensionamento invoca "setFn" che ottiene la larghezza della finestra e salva come "originalWindowSize". Quindi invoca "checkFn" che dopo 500ms (o le tue preferenze) ottiene la dimensione della finestra corrente e confronta l'originale con quello attuale, se non sono gli stessi, la finestra viene comunque ridimensionata. Non dimenticare di rimuovere i messaggi della console durante la produzione e (facoltativo) può rendere l'auto-esecuzione "setFn".
var resizeTimer;
$( window ).resize(function() {
if(resizeTimer){
clearTimeout(resizeTimer);
}
resizeTimer = setTimeout(function() {
//your code here
resizeTimer = null;
}, 200);
});
Questo ha funzionato per quello che stavo cercando di fare in Chrome. Questo non attiverà il callback fino a 200 ms dopo l'ultimo evento di ridimensionamento.
Una migliore alternativa creata anche da me è qui: https://stackoverflow.com/a/23692008/2829600 (supporta "funzioni di eliminazione")
Ho scritto questa semplice funzione per gestire il ritardo nell'esecuzione, utile all'interno di jQuery .scroll () e .resize () Quindi callback_f verrà eseguito una sola volta per una stringa id specifica.
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 ... }); });
:? Altrimenti codice abbastanza pulito. Grazie per la condivisione. :)
Ho implementato la funzione che attiva due eventi sull'elemento DOM utente:
Codice:
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...
}
Non so se il mio codice funziona per altri, ma è davvero un ottimo lavoro per me. Ho avuto questa idea analizzando il codice Dolan Antenucci perché la sua versione non funziona per me e spero davvero che possa essere utile a qualcuno.
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);
}
Ho scritto una funzione che passa una funzione se racchiusa in qualsiasi evento di ridimensionamento. Utilizza un intervallo in modo che il ridimensionamento non crei costantemente eventi di timeout. Ciò consente di eseguire indipendentemente dall'evento di ridimensionamento diverso da una voce di registro che deve essere rimossa in produzione.
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()
così si esegue solo dopo aver fatto tutto il ridimensionamento e non ancora e ancora?