Also benutze ich momentan so etwas wie:
$(window).resize(function(){resizedw();});
Dies wird jedoch viele Male aufgerufen, während die Größenänderung fortgesetzt wird. Ist es möglich, ein Ereignis zu erfassen, wenn es endet?
Also benutze ich momentan so etwas wie:
$(window).resize(function(){resizedw();});
Dies wird jedoch viele Male aufgerufen, während die Größenänderung fortgesetzt wird. Ist es möglich, ein Ereignis zu erfassen, wenn es endet?
Antworten:
Ich hatte Glück mit der folgenden Empfehlung: http://forum.jquery.com/topic/the-resizeend-event
Hier ist der Code, damit Sie nicht den Link und die Quelle seines Beitrags durchsuchen müssen:
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');
}
}
Danke sime.vidas für den Code!
new Date(-1E12)
B. JSLint warnt vor der Verwendung 00
.
rtime: Date; .... if (+new Date() - +rtime < delta)
und in Typoskript sollte die Größenänderungsfunktion eine Pfeilfunktion wie diese sein resizeend=()=>
. Da in der Funktion this
zum Ändern der Größe auf das Fensterobjekt verweisen.
Sie können setTimeout()
und verwendenclearTimeout()
function resizedw(){
// Haven't resized in 100ms!
}
var doit;
window.onresize = function(){
clearTimeout(doit);
doit = setTimeout(resizedw, 100);
};
Codebeispiel auf jsfiddle .
Dies ist der Code, den ich gemäß der Antwort von @Mark Coleman schreibe:
$(window).resize(function() {
clearTimeout(window.resizedFinished);
window.resizedFinished = setTimeout(function(){
console.log('Resized finished.');
}, 250);
});
Danke Mark!
resizeTimer
eine globale Variable, dh sie ist nicht definiert window
, also genau so wie hier. Nur dieses Beispiel ist besser, da Sie die Variable nicht extern definieren müssen. Es ist auch sinnvoll, diese Variable zum window
Objekt hinzuzufügen, da dies das Objekt ist, an das der Ereignis-Listener gebunden ist.
Internet Explorer bietet ein resizeEnd Ereignis. Andere Browser lösen das Größenänderungsereignis viele Male aus, während Sie die Größe ändern.
Hier finden Sie weitere gute Antworten, die zeigen, wie Sie setTimeout und das .throttle verwenden ..debounce- Methoden von lodash und Unterstrich, daher werde ich Ben Almans jQuery-Plugin für die Drosselklappenentprellung erwähnen das erreicht, wonach Sie .
Angenommen, Sie haben diese Funktion, die Sie nach einer Größenänderung auslösen möchten:
function onResize() {
console.log("Resize just happened!");
};
Drosselklappenbeispiel
Im folgenden Beispiel onResize()
wird während einer Fenstergrößenänderung nur einmal alle 250 Millisekunden aufgerufen.
$(window).resize( $.throttle( 250, onResize) );
Entprellungsbeispiel
Im folgenden Beispiel onResize()
wird nur einmal am Ende einer Fenstergrößenänderungsaktion aufgerufen. Dies erzielt das gleiche Ergebnis, das @Mark in seiner Antwort präsentiert.
$(window).resize( $.debounce( 250, onResize) );
Mit Underscore.js gibt es eine elegante Lösung. Wenn Sie sie also in Ihrem Projekt verwenden, können Sie Folgendes tun:
$( window ).resize( _.debounce( resizedw, 500 ) );
Das sollte reichen :) Aber wenn Sie mehr darüber lesen möchten, können Sie meinen Blog-Beitrag lesen - http://rifatnabi.com/post/detect-end-of-jquery-resize-event-using-underscore -debounce (Deadlink)
lodash
Eine Lösung besteht darin, jQuery um eine Funktion zu erweitern, z. 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));
});
};
Beispielnutzung:
$(window).resized(myHandler, 300);
Sie können eine Referenz-ID für jedes setInterval oder setTimeout speichern. So was:
var loop = setInterval(func, 30);
// some time later clear the interval
clearInterval(loop);
Um dies ohne eine "globale" Variable zu tun, können Sie der Funktion selbst eine lokale Variable hinzufügen. Ex:
$(window).resize(function() {
clearTimeout(this.id);
this.id = setTimeout(doneResizing, 500);
});
function doneResizing(){
$("body").append("<br/>done!");
}
Sie können verwenden setTimeout()
und clearTimeout()
in Verbindung mit jQuery.data
:
$(window).resize(function() {
clearTimeout($.data(this, 'resizeTimer'));
$.data(this, 'resizeTimer', setTimeout(function() {
//do something
alert("Haven't resized in 200ms!");
}, 200));
});
Aktualisieren
Ich habe eine Erweiterung geschrieben , um den Standard on
(& bind
) -Event-Handler von jQuery zu verbessern . Es fügt den ausgewählten Elementen eine Ereignishandlerfunktion für ein oder mehrere Ereignisse hinzu, wenn das Ereignis für ein bestimmtes Intervall nicht ausgelöst wurde. Dies ist nützlich, wenn Sie einen Rückruf erst nach einer Verzögerung auslösen möchten, z. B. nach dem Größenänderungsereignis oder sonst.
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));
Verwenden Sie es wie jeden anderen on
oder bind
-event-Handler, außer dass Sie als letzten einen zusätzlichen Parameter übergeben können:
$(window).on('resize', function(e) {
console.log(e.type + '-event was 200ms not triggered');
}, 200);
Es gibt eine viel einfachere Methode, um eine Funktion am Ende der Größenänderung auszuführen, als die Deltazeit zwischen zwei Aufrufen zu berechnen. Gehen Sie einfach so vor:
var resizeId;
$(window).resize(function() {
clearTimeout(resizeId);
resizeId = setTimeout(resizedEnded, 500);
});
function resizedEnded(){
...
}
Und das Äquivalent für Angular2 :
private resizeId;
@HostListener('window:resize', ['$event'])
onResized(event: Event) {
clearTimeout(this.resizeId);
this.resizeId = setTimeout(() => {
// Your callback method here.
}, 500);
}
Verwenden Sie für die Winkelmethode die () => { }
Notation in setTimeout
, um den Gültigkeitsbereich beizubehalten. Andernfalls können Sie keine Funktionsaufrufe ausführen oder verwenden this
.
Dies ist eine Modifikation des obigen Dolan-Codes. Ich habe eine Funktion hinzugefügt, die die Fenstergröße zu Beginn der Größenänderung überprüft und mit der Größe am Ende der Größenänderung vergleicht, wenn die Größe entweder größer oder kleiner als der Rand ist ( zB 1000) dann wird es neu geladen.
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;
}
Mark Colemans Antwort ist sicherlich weitaus besser als die ausgewählte Antwort, aber wenn Sie die globale Variable für die Timeout-ID (die doit
Variable in Marks Antwort) , können Sie eine der folgenden :
(1) Verwenden Sie einen sofort aufgerufenen Funktionsausdruck (IIFE), um einen Abschluss zu erstellen.
$(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) Verwenden Sie eine Eigenschaft der Ereignishandlerfunktion.
$(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);
});
Ich habe selbst eine kleine Wrapper-Funktion geschrieben ...
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);
});
};
Hier ist die Verwendung:
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(){
//...
});
Nun, für den Fenstermanager ist jedes Größenänderungsereignis eine eigene Nachricht mit einem unterschiedlichen Anfang und Ende. Technisch gesehen ist es also jedes Mal das Ende, wenn die Fenstergröße geändert wird .
Vielleicht möchten Sie Ihre Fortsetzung jedoch verzögern? Hier ist ein Beispiel.
var t = -1;
function doResize()
{
document.write('resize');
}
$(document).ready(function(){
$(window).resize(function(){
clearTimeout(t);
t = setTimeout(doResize, 1000);
});
});
Hier ist ein SEHR einfaches Skript, um sowohl ein 'resizestart'- als auch ein' resizeend'-Ereignis für das Fensterobjekt auszulösen.
Es ist nicht nötig, sich mit Datum und Uhrzeit zu beschäftigen.
Die d
Variable gibt die Anzahl der Millisekunden zwischen Größenänderungsereignissen vor dem Auslösen des Größenänderungs-Endereignisses an. Sie können damit spielen, um die Empfindlichkeit des Endereignisses zu ändern.
Um diese Ereignisse anzuhören, müssen Sie lediglich Folgendes tun:
resizestart: $(window).on('resizestart', function(event){console.log('Resize Start!');});
Größe ändern:
$(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));
Dies ist, was ich zum Verzögern von wiederholten Aktionen verwende. Es kann an mehreren Stellen in Ihrem Code aufgerufen werden:
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);
};
};
Verwendung:
$(window).resize(function () {
debounce(function() {
//...
}, 500);
});
da die ausgewählte Antwort nicht wirklich funktioniert hat .. und wenn Sie jquery nicht verwenden, finden Sie hier eine einfache Drosselfunktion mit einem Beispiel für die Verwendung bei der Fenstergrößenänderung
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();
}
Dies funktionierte für mich, da ich keine Plugins verwenden wollte.
$(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();
});
Rufen Sie beim Ändern der Fenstergröße "setFn" auf, um die Fensterbreite abzurufen, und speichern Sie sie als "originalWindowSize". Rufen Sie dann "checkFn" auf, das nach 500 ms (oder Ihrer Präferenz) die aktuelle Fenstergröße erhält und das Original mit der aktuellen vergleicht. Wenn diese nicht identisch sind, wird die Größe des Fensters immer noch geändert. Vergessen Sie nicht, Konsolenmeldungen in der Produktion zu entfernen, und (optional) kann "setFn" selbst ausführen.
var resizeTimer;
$( window ).resize(function() {
if(resizeTimer){
clearTimeout(resizeTimer);
}
resizeTimer = setTimeout(function() {
//your code here
resizeTimer = null;
}, 200);
});
Dies funktionierte für das, was ich in Chrom versuchte. Der Rückruf wird erst 200 ms nach dem letzten Größenänderungsereignis ausgelöst.
Eine bessere Alternative, die auch von mir erstellt wurde, ist hier: https://stackoverflow.com/a/23692008/2829600 (unterstützt "Löschfunktionen")
Ich habe diese einfache Funktion zur Behandlung von Ausführungsverzögerungen geschrieben, die in jQuery .scroll () und .resize () nützlich ist. Daher wird callback_f für eine bestimmte ID-Zeichenfolge nur einmal ausgeführt.
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 ... }); });
? Ansonsten ziemlich sauberer Code. Danke für das Teilen. :)
Ich habe eine Funktion implementiert, die zwei Ereignisse im Benutzer-DOM-Element auslöst:
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...
}
Ich weiß nicht, ob mein Code für andere funktioniert, aber es macht wirklich einen tollen Job für mich. Ich kam auf diese Idee, indem ich Dolan Antenucci-Code analysierte, weil seine Version für mich nicht funktioniert und ich hoffe wirklich, dass sie jemandem helfen wird.
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);
}
Ich habe eine Funktion geschrieben, die eine Funktion übergibt, wenn sie in ein Größenänderungsereignis eingeschlossen wird. Es wird ein Intervall verwendet, damit die Größenänderung nicht ständig Timeout-Ereignisse erzeugt. Auf diese Weise kann es unabhängig vom Größenänderungsereignis ausgeführt werden, mit Ausnahme eines Protokolleintrags, der in der Produktion entfernt werden soll.
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()
damit es erst ausgeführt wird, nachdem alle Größenänderungen vorgenommen wurden und nicht immer wieder?