Więc obecnie używam czegoś takiego:
$(window).resize(function(){resizedw();});
Ale jest to wywoływane wiele razy podczas procesu zmiany rozmiaru. Czy można złapać wydarzenie, gdy się skończy?
Więc obecnie używam czegoś takiego:
$(window).resize(function(){resizedw();});
Ale jest to wywoływane wiele razy podczas procesu zmiany rozmiaru. Czy można złapać wydarzenie, gdy się skończy?
Odpowiedzi:
Miałem szczęście z następującą rekomendacją: http://forum.jquery.com/topic/the-resizeend-event
Oto kod, więc nie musisz przekopywać linku i źródła jego postu:
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');
}
}
Dzięki sime.vidas za kod!
new Date(-1E12)
- tzn. JSLint ostrzega przed użyciem 00
.
rtime: Date; .... if (+new Date() - +rtime < delta)
a w funkcji zmiany rozmiaru maszynopisu powinna być taka funkcja strzałkiresizeend=()=>
. Ponieważ w funkcji zmiany rozmiaru this
odwołanie do obiektu okna.
Możesz użyć setTimeout()
iclearTimeout()
function resizedw(){
// Haven't resized in 100ms!
}
var doit;
window.onresize = function(){
clearTimeout(doit);
doit = setTimeout(resizedw, 100);
};
Przykład kodu na jsfiddle .
$(document)
, wykrywanie myszy byłoby ograniczone do użytkowników z systemem Microsoft Windows i wrażliwymi wersjami jego przeglądarki Internet Explorer: iedataleak.spider.io/demo
Oto kod, który piszę zgodnie z odpowiedzią @Mark Coleman:
$(window).resize(function() {
clearTimeout(window.resizedFinished);
window.resizedFinished = setTimeout(function(){
console.log('Resized finished.');
}, 250);
});
Dzięki Mark!
resizeTimer
jest zmienną globalną, co oznacza, że nie jest zdefiniowana window
, więc jest dokładnie taka sama jak tutaj, tylko ten przykład jest lepszy, ponieważ nie musisz definiować zmiennej zewnętrznie. i sensowne jest również dodanie tej zmiennej do window
obiektu, ponieważ jest to obiekt, z którym powiązany jest detektor zdarzeń.
Internet Explorer zapewnia zdarzenie resizeEnd . Inne przeglądarki wyzwalają zdarzenie zmiany rozmiaru wiele razy podczas zmiany rozmiaru.
Są tutaj inne świetne odpowiedzi, które pokazują, jak używać setTimeout i .throttle ,.debounce metody z lodash i podkreślenia, więc będę wspomnieć Ben Alman za przepustnicę-nieczułości jQuery plugin , który realizuje to, czego szukasz.
Załóżmy, że masz tę funkcję, którą chcesz uruchomić po zmianie rozmiaru:
function onResize() {
console.log("Resize just happened!");
};
Przykład przepustnicy
W poniższym przykładzie onResize()
będzie wywoływana tylko raz na 250 milisekund podczas zmiany rozmiaru okna.
$(window).resize( $.throttle( 250, onResize) );
Przykład odbicia
W poniższym przykładzie onResize()
zostanie wywołany tylko raz na końcu akcji zmiany rozmiaru okna. Osiąga to ten sam wynik, który @Mark przedstawia w swojej odpowiedzi.
$(window).resize( $.debounce( 250, onResize) );
Istnieje eleganckie rozwiązanie wykorzystujące Underscore.js. Jeśli więc używasz go w swoim projekcie, możesz wykonać następujące czynności -
$( window ).resize( _.debounce( resizedw, 500 ) );
To powinno wystarczyć :) Ale jeśli chcesz przeczytać więcej na ten temat, możesz sprawdzić mój post na blogu - http://rifatnabi.com/post/detect-end-of-jquery-resize-event-using-underscore -debounce ( martwy link )
lodash
Jednym z rozwiązań jest rozszerzenie jQuery o funkcję, np .: 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));
});
};
Przykładowe użycie:
$(window).resized(myHandler, 300);
Możesz przechowywać identyfikator odwołania do dowolnego setInterval lub setTimeout. Lubię to:
var loop = setInterval(func, 30);
// some time later clear the interval
clearInterval(loop);
Aby to zrobić bez zmiennej „globalnej”, możesz dodać zmienną lokalną do samej funkcji. Dawny:
$(window).resize(function() {
clearTimeout(this.id);
this.id = setTimeout(doneResizing, 500);
});
function doneResizing(){
$("body").append("<br/>done!");
}
Można używać setTimeout()
i clearTimeout()
w połączeniu z jQuery.data
:
$(window).resize(function() {
clearTimeout($.data(this, 'resizeTimer'));
$.data(this, 'resizeTimer', setTimeout(function() {
//do something
alert("Haven't resized in 200ms!");
}, 200));
});
Aktualizacja
Napisałem rozszerzenie, aby ulepszyć domyślną on
(& bind
) -event-handler jQuery . Dołącza funkcję obsługi zdarzenia dla jednego lub więcej zdarzeń do wybranych elementów, jeśli zdarzenie nie zostało wyzwolone dla danego interwału. Jest to przydatne, jeśli chcesz uruchomić oddzwonienie dopiero po opóźnieniu, takim jak zdarzenie zmiany rozmiaru lub inne.
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));
Używaj go jak każdego innego on
lub bind
-event obsługi, z tym wyjątkiem, że możesz przekazać dodatkowy parametr jako ostatni:
$(window).on('resize', function(e) {
console.log(e.type + '-event was 200ms not triggered');
}, 200);
Istnieje znacznie prostsza metoda wykonania funkcji na końcu zmiany rozmiaru niż obliczenie czasu delta między dwoma wywołaniami, po prostu zrób to w następujący sposób:
var resizeId;
$(window).resize(function() {
clearTimeout(resizeId);
resizeId = setTimeout(resizedEnded, 500);
});
function resizedEnded(){
...
}
I odpowiednik Angular2 :
private resizeId;
@HostListener('window:resize', ['$event'])
onResized(event: Event) {
clearTimeout(this.resizeId);
this.resizeId = setTimeout(() => {
// Your callback method here.
}, 500);
}
W przypadku metody kątowej użyj () => { }
zapisu w, setTimeout
aby zachować zakres, w przeciwnym razie nie będziesz w stanie wykonywać żadnych wywołań funkcji ani ich używać this
.
Jest to modyfikacja powyższego kodu Dolana, dodałem funkcję, która sprawdza rozmiar okna na początku zmiany rozmiaru i porównuje go z wielkością na końcu zmiany rozmiaru, jeśli rozmiar jest większy lub mniejszy niż margines ( np. 1000), a następnie przeładowuje.
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;
}
Odpowiedź Marka Colemana jest zdecydowanie lepsza niż wybrana odpowiedź, ale jeśli chcesz uniknąć zmiennej globalnej dla identyfikatora limitu czasu ( doit
zmiennej w odpowiedzi Marka), możesz wykonać jedną z następujących czynności:
(1) Użyj natychmiast wywołanego wyrażenia funkcyjnego (IIFE), aby utworzyć zamknięcie.
$(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) Użyj właściwości funkcji obsługi zdarzeń.
$(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);
});
sam napisałem funkcję owijania litte ...
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);
});
};
Oto użycie:
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(){
//...
});
Cóż, jeśli chodzi o menedżera okien, każde zdarzenie zmiany rozmiaru jest własnym komunikatem, z wyraźnym początkiem i końcem, więc technicznie rzecz biorąc, za każdym razem, gdy zmienia się rozmiar okna, jest to koniec.
Powiedziawszy to, może chcesz opóźnić swoją kontynuację? Oto przykład.
var t = -1;
function doResize()
{
document.write('resize');
}
$(document).ready(function(){
$(window).resize(function(){
clearTimeout(t);
t = setTimeout(doResize, 1000);
});
});
Oto BARDZO prosty skrypt, który wyzwala zarówno zdarzenie „resizestart”, jak i „resizeend” na obiekcie okna.
Nie ma potrzeby marnowania czasu i dat.
The d
Zmienna reprezentuje liczbę milisekund między zdarzenia zmiany rozmiaru przed wywołaniem zdarzenia zakończenia zmiany rozmiaru, można grać z tym, aby zmienić sposób wrażliwy zdarzenie koniec jest.
Aby wysłuchać tych wydarzeń, wystarczy:
resizestart: $(window).on('resizestart', function(event){console.log('Resize Start!');});
zmiana rozmiaru:
$(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));
To jest to, czego używam do opóźniania powtarzających się działań, można je wywołać w wielu miejscach w kodzie:
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);
};
};
Stosowanie:
$(window).resize(function () {
debounce(function() {
//...
}, 500);
});
ponieważ wybrana odpowiedź tak naprawdę nie działała .. a jeśli nie używasz jquery, tutaj jest prosta funkcja przepustnicy z przykładem użycia jej przy zmianie rozmiaru okna
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();
}
działało to dla mnie, ponieważ nie chciałem używać żadnych wtyczek.
$(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();
});
Przy ponownym rozmiarze okna wywołaj „setFn”, który pobierze szerokość okna i zapisz jako „originalWindowSize”. Następnie wywołaj „checkFn”, który po 500 ms (lub twoich preferencjach) pobiera bieżący rozmiar okna i porównuje oryginał z bieżącym, jeśli nie są one takie same, wówczas okno jest ponownie zmieniane. Nie zapomnij usunąć komunikatów konsoli podczas produkcji, a (opcjonalnie) samoczynnie uruchomi się „setFn”.
var resizeTimer;
$( window ).resize(function() {
if(resizeTimer){
clearTimeout(resizeTimer);
}
resizeTimer = setTimeout(function() {
//your code here
resizeTimer = null;
}, 200);
});
To działało dla tego, co próbowałem zrobić w chromie. Spowoduje to oddzwonienie dopiero po 200 ms od ostatniego zdarzenia zmiany rozmiaru.
Lepsza alternatywa również stworzona przeze mnie jest tutaj: https://stackoverflow.com/a/23692008/2829600 (obsługuje „funkcje usuwania”)
Napisałem tę prostą funkcję do obsługi opóźnienia w wykonaniu, przydatną w jQuery .scroll () i .resize () Tak więc callback_f uruchomi się tylko raz dla określonego ciągu id.
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 ... }); });
? W przeciwnym razie całkiem czysty kod. Dzięki za udostępnienie. :)
Zaimplementowałem funkcję, która wyzwala dwa zdarzenia w elemencie DOM użytkownika:
Kod:
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...
}
Nie wiem, czy mój kod działa na innych, ale naprawdę robi dla mnie świetną robotę. Wpadłem na ten pomysł, analizując kod Dolan Antenucci, ponieważ jego wersja nie działa dla mnie i naprawdę mam nadzieję, że będzie komuś pomocny.
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);
}
Napisałem funkcję, która przekazuje funkcję, gdy jest opakowana w dowolne zdarzenie zmiany rozmiaru. Używa interwału, aby zmiana rozmiaru nawet nie powodowała ciągłego przekroczenia limitu czasu. Dzięki temu może wykonywać niezależnie od zdarzenia zmiany rozmiaru innego niż wpis dziennika, który powinien zostać usunięty podczas produkcji.
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()
aby działało tylko po zakończeniu zmiany rozmiaru, a nie w kółko?