Así que actualmente uso algo como:
$(window).resize(function(){resizedw();});
Pero esto se llama muchas veces mientras continúa el proceso de cambio de tamaño. ¿Es posible atrapar un evento cuando termina?
Así que actualmente uso algo como:
$(window).resize(function(){resizedw();});
Pero esto se llama muchas veces mientras continúa el proceso de cambio de tamaño. ¿Es posible atrapar un evento cuando termina?
Respuestas:
Tuve suerte con la siguiente recomendación: http://forum.jquery.com/topic/the-resizeend-event
Aquí está el código para que no tenga que buscar en el enlace y la fuente de su publicación:
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');
}
}
Gracias sime.vidas por el código!
new Date(-1E12)
, es decir, JSLint advierte sobre el uso 00
.
rtime: Date; .... if (+new Date() - +rtime < delta)
y en la función resizeend mecanografiada debe ser la función de flecha como esta resizeend=()=>
. Porque en la función resizeend, this
referencia al objeto de ventana.
Puedes usar setTimeout()
yclearTimeout()
function resizedw(){
// Haven't resized in 100ms!
}
var doit;
window.onresize = function(){
clearTimeout(doit);
doit = setTimeout(resizedw, 100);
};
Ejemplo de código en jsfiddle .
$(document)
, la detección del mouse se limitaría a los usuarios que ejecutan Microsoft Windows y versiones vulnerables de su Internet Explorer: iedataleak.spider.io/demo
Este es el código que escribo según la respuesta de @Mark Coleman:
$(window).resize(function() {
clearTimeout(window.resizedFinished);
window.resizedFinished = setTimeout(function(){
console.log('Resized finished.');
}, 250);
});
Gracias Mark!
resizeTimer
es una variable global, lo que significa que no está definida window
, por lo que es exactamente la misma que aquí, solo que este ejemplo es mejor ya que no necesita definir la variable externamente. y también tiene sentido agregar esta variable al window
objeto ya que ese es el objeto al que está vinculado el detector de eventos.
Internet Explorer proporciona un evento resizeEnd . Otros navegadores activarán el evento de cambio de tamaño muchas veces mientras cambia el tamaño.
Aquí hay otras excelentes respuestas que muestran cómo usar setTimeout y .throttle ,.debounce métodos de lodash y subrayado, por lo que mencionaré el plugin jQuery de Ben Alman para reducir y eliminar el rebote que logra lo que buscas.
Supongamos que tiene esta función que desea activar después de un cambio de tamaño:
function onResize() {
console.log("Resize just happened!");
};
Ejemplo de aceleración
En el siguiente ejemplo, onResize()
solo se llamará una vez cada 250 milisegundos durante el cambio de tamaño de una ventana.
$(window).resize( $.throttle( 250, onResize) );
Ejemplo de rebote
En el siguiente ejemplo, onResize()
solo se llamará una vez al final de una acción de cambio de tamaño de ventana. Esto logra el mismo resultado que @Mark presenta en su respuesta.
$(window).resize( $.debounce( 250, onResize) );
Hay una solución elegante usando el Underscore.js Entonces, si lo está usando en su proyecto, puede hacer lo siguiente:
$( window ).resize( _.debounce( resizedw, 500 ) );
Esto debería ser suficiente :) Pero, si está interesado en leer más sobre eso, puede consultar la publicación de mi blog: http://rifatnabi.com/post/detect-end-of-jquery-resize-event-using-underscore -debounce (deadlink)
lodash
también proporcione esto
Una solución es extender jQuery con una función, por ejemplo: 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));
});
};
Uso de la muestra:
$(window).resized(myHandler, 300);
Puede almacenar una identificación de referencia en cualquier setInterval o setTimeout. Me gusta esto:
var loop = setInterval(func, 30);
// some time later clear the interval
clearInterval(loop);
Para hacer esto sin una variable "global", puede agregar una variable local a la función misma. Ex:
$(window).resize(function() {
clearTimeout(this.id);
this.id = setTimeout(doneResizing, 500);
});
function doneResizing(){
$("body").append("<br/>done!");
}
Puede usar setTimeout()
y clearTimeout()
junto con jQuery.data
:
$(window).resize(function() {
clearTimeout($.data(this, 'resizeTimer'));
$.data(this, 'resizeTimer', setTimeout(function() {
//do something
alert("Haven't resized in 200ms!");
}, 200));
});
Actualizar
Escribí una extensión para mejorar el controlador predeterminado on
(& bind
) -event-handler de jQuery. Adjunta una función de controlador de eventos para uno o más eventos a los elementos seleccionados si el evento no se activó durante un intervalo determinado. Esto es útil si desea activar una devolución de llamada solo después de un retraso, como el evento de cambio de tamaño, o de lo contrario.
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));
Utilizarlo como cualquier otro on
o bind
-Evento manipulador, excepto que se puede pasar un parámetro adicional como último:
$(window).on('resize', function(e) {
console.log(e.type + '-event was 200ms not triggered');
}, 200);
Hay un método mucho más simple para ejecutar una función al final del cambio de tamaño que calcular el tiempo delta entre dos llamadas, simplemente hazlo así:
var resizeId;
$(window).resize(function() {
clearTimeout(resizeId);
resizeId = setTimeout(resizedEnded, 500);
});
function resizedEnded(){
...
}
Y el equivalente para Angular2 :
private resizeId;
@HostListener('window:resize', ['$event'])
onResized(event: Event) {
clearTimeout(this.resizeId);
this.resizeId = setTimeout(() => {
// Your callback method here.
}, 500);
}
Para el método angular, use la () => { }
notación en setTimeout
para preservar el alcance, de lo contrario no podrá realizar llamadas a funciones ni usarlas this
.
Esta es una modificación del código de Dolan anterior, agregué una función que verifica el tamaño de la ventana al comienzo del cambio de tamaño y lo compara con el tamaño al final del cambio de tamaño, si el tamaño es mayor o menor que el margen ( por ejemplo, 1000) luego se recarga.
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 respuesta de Mark Coleman es ciertamente mucho mejor que la respuesta seleccionada, pero si desea evitar la variable global para el ID de tiempo de espera (la doit
variable en la respuesta de Mark), puede hacer una de las siguientes cosas:
(1) Use una expresión de función invocada inmediatamente (IIFE) para crear un cierre.
$(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) Use una propiedad de la función de controlador de eventos.
$(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);
});
Escribí una pequeña función de envoltura por mi cuenta ...
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);
});
};
Aquí está el 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(){
//...
});
Bueno, en lo que respecta al administrador de ventanas, cada evento de cambio de tamaño es su propio mensaje, con un comienzo y un final distintos, por lo que técnicamente, cada vez que se cambia el tamaño de la ventana, es el final.
Habiendo dicho eso, ¿tal vez quieres retrasar tu continuación? Aquí hay un ejemplo.
var t = -1;
function doResize()
{
document.write('resize');
}
$(document).ready(function(){
$(window).resize(function(){
clearTimeout(t);
t = setTimeout(doResize, 1000);
});
});
Aquí hay un script MUY simple para desencadenar un evento 'resizestart' y 'resizeend' en el objeto de la ventana.
No hay necesidad de perder el tiempo con fechas y horas.
La d
variable representa el número de milisegundos entre los eventos de cambio de tamaño antes de activar el evento final de cambio de tamaño, puede jugar con esto para cambiar la sensibilidad del evento final.
Para escuchar estos eventos todo lo que necesita hacer es:
reiniciar: $(window).on('resizestart', function(event){console.log('Resize Start!');});
redimensionar:
$(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));
Esto es lo que uso para retrasar las acciones repetidas, se puede llamar en varios lugares en su código:
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);
});
dado que la respuesta seleccionada en realidad no funcionó ... y si no está usando jquery, aquí hay una función de acelerador simple con un ejemplo de cómo usarla con el cambio de tamaño de la ventana
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();
}
esto funcionó para mí ya que no quería usar ningún complemento.
$(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();
});
En el cambio de tamaño de la ventana, invoque "setFn", que obtiene el ancho de la ventana y lo guarda como "originalWindowSize". Luego invoque "checkFn", que después de 500 ms (o su preferencia) obtiene el tamaño actual de la ventana y compara el original con el actual, si no son iguales, entonces la ventana todavía se está redimensionando. No olvide eliminar los mensajes de la consola en producción, y (opcional) puede hacer que "setFn" se ejecute automáticamente.
var resizeTimer;
$( window ).resize(function() {
if(resizeTimer){
clearTimeout(resizeTimer);
}
resizeTimer = setTimeout(function() {
//your code here
resizeTimer = null;
}, 200);
});
Esto funcionó para lo que estaba tratando de hacer en Chrome. Esto no activará la devolución de llamada hasta 200 ms después del último evento de cambio de tamaño.
Una mejor alternativa también creada por mí está aquí: https://stackoverflow.com/a/23692008/2829600 (admite "eliminar funciones")
Escribí esta función simple para manejar el retraso en la ejecución, útil dentro de jQuery .scroll () y .resize () Entonces callback_f se ejecutará solo una vez para una cadena de identificación específica.
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 ... }); });
:? Código bastante limpio de lo contrario. Gracias por compartir. :)
Implementé la función que desencadena dos eventos en el elemento DOM del usuario:
Código:
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...
}
No sé si mi código funciona para otros, pero realmente hace un gran trabajo para mí. Tengo esta idea analizando el código de Dolan Antenucci porque su versión no me funciona y realmente espero que sea útil para alguien.
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);
}
Escribí una función que pasa una función cuando se envuelve en cualquier evento de cambio de tamaño. Utiliza un intervalo para que el cambio de tamaño incluso no esté creando constantemente eventos de tiempo de espera. Esto le permite funcionar independientemente del evento de cambio de tamaño que no sea una entrada de registro que debe eliminarse en producción.
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()
para que solo se ejecute después de que se haya realizado el cambio de tamaño y no una y otra vez?