Тому я зараз використовую щось на зразок:
$(window).resize(function(){resizedw();});
Але це називається багато разів, поки триває процес зміни розміру. Чи можливо зловити подію, коли вона закінчиться?
Тому я зараз використовую щось на зразок:
$(window).resize(function(){resizedw();});
Але це називається багато разів, поки триває процес зміни розміру. Чи можливо зловити подію, коли вона закінчиться?
Відповіді:
Мені пощастило з такою рекомендацією: http://forum.jquery.com/topic/the-resizeend-event
Ось код, щоб вам не довелося копати посилання та джерело його публікації:
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');
}
}
Дякую sime.vidas за код!
new Date(-1E12)
- тобто JSLint попереджає про використання 00
.
rtime: Date; .... if (+new Date() - +rtime < delta)
а в typecript resizeend функція повинна бути такою, як ця стрілка resizeend=()=>
. Тому що у функції resizeend this
посилання на об’єкт вікна.
Ви можете використовувати setTimeout()
іclearTimeout()
function resizedw(){
// Haven't resized in 100ms!
}
var doit;
window.onresize = function(){
clearTimeout(doit);
doit = setTimeout(resizedw, 100);
};
Приклад коду на jsfiddle .
$(document)
, виявлення миші обмежене лише користувачами під керуванням Microsoft Windows та вразливими версіями її Internet Explorer: iedataleak.spider.io/demo
Це код, який я пишу відповідно до відповіді @Mark Coleman:
$(window).resize(function() {
clearTimeout(window.resizedFinished);
window.resizedFinished = setTimeout(function(){
console.log('Resized finished.');
}, 250);
});
Дякую Марку!
resizeTimer
є глобальною змінною, це означає, що вона визначена no the window
, тому вона точно така ж, як і тут, тільки цей приклад краще, оскільки вам не потрібно визначати змінну зовні. і також має сенс додати цю змінну до window
об'єкта, оскільки це Об'єкт, до якого прив'язується слухач подій.
Internet Explorer надає подію resizeEnd . Інші веб-переглядачі будуть багато разів запускати подію зміни розміру під час зміни розміру.
Тут є інші чудові відповіді, які показують, як використовувати setTimeout та .throttle ,.debounce методи від lodash і підкреслюють, тому я згадаю плагін jQuery з дросельним дебютом Бен Альмана, який виконує те, що ви хочете.
Припустимо, у вас є ця функція, яку ви хочете запустити після зміни розміру:
function onResize() {
console.log("Resize just happened!");
};
Приклад дросельної заслінки
У наступному прикладі onResize()
буде викликатися лише раз на 250 мілісекунд під час зміни розміру вікна.
$(window).resize( $.throttle( 250, onResize) );
Приклад дебютації
У наступному прикладі onResize()
буде викликано лише один раз у кінці дії зміни розміру вікна. Це досягає того ж результату, що і @Mark у своїй відповіді.
$(window).resize( $.debounce( 250, onResize) );
Існує елегантне рішення за допомогою Underscore.js Отже, якщо ви використовуєте його у своєму проекті, ви можете зробити наступне -
$( window ).resize( _.debounce( resizedw, 500 ) );
Цього має бути достатньо :) Але, якщо вам цікаво прочитати більше про це, ви можете перевірити мій пост у блозі - http://rifatnabi.com/post/detect-end-of-jquery-resize-event-using-underscore -відступ (мертве посилання)
lodash
також забезпечують це
Одне рішення - це розширити jQuery з функцією, наприклад: 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));
});
};
Використання зразка:
$(window).resized(myHandler, 300);
Ви можете зберігати ідентифікатор посилання на будь-який набірInterval або setTimeout. Подобається це:
var loop = setInterval(func, 30);
// some time later clear the interval
clearInterval(loop);
Для цього без "глобальної" змінної ви можете додати локальну змінну до самої функції. Наприклад:
$(window).resize(function() {
clearTimeout(this.id);
this.id = setTimeout(doneResizing, 500);
});
function doneResizing(){
$("body").append("<br/>done!");
}
Ви можете використовувати setTimeout()
і clearTimeout()
в поєднанні з jQuery.data
:
$(window).resize(function() {
clearTimeout($.data(this, 'resizeTimer'));
$.data(this, 'resizeTimer', setTimeout(function() {
//do something
alert("Haven't resized in 200ms!");
}, 200));
});
Оновлення
Я написав розширення, щоб поліпшити jQuery за замовчуванням on
(& bind
) -event-handler. Він додає функцію обробника подій для однієї або декількох подій до вибраних елементів, якщо подія не була запущена протягом заданого інтервалу. Це корисно, якщо ви хочете запустити зворотний дзвінок лише після затримки, як-от подія зміни розміру чи інше.
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));
Використовуйте його як будь-який інший on
або bind
-event обробник, за винятком того, що ви можете передавати додатковий параметр як останній:
$(window).on('resize', function(e) {
console.log(e.type + '-event was 200ms not triggered');
}, 200);
Існує набагато простіший метод виконання функції в кінці розміру, ніж обчислення часу дельти між двома викликами, просто зробіть це так:
var resizeId;
$(window).resize(function() {
clearTimeout(resizeId);
resizeId = setTimeout(resizedEnded, 500);
});
function resizedEnded(){
...
}
І еквівалент для Angular2 :
private resizeId;
@HostListener('window:resize', ['$event'])
onResized(event: Event) {
clearTimeout(this.resizeId);
this.resizeId = setTimeout(() => {
// Your callback method here.
}, 500);
}
Для кутового методу використовуйте () => { }
позначення в програмі setTimeout
для збереження області, інакше ви не зможете робити жодних викликів функцій або використовувати this
.
Це модифікація коду Долана вище, я додав функцію, яка перевіряє розмір вікна на початку зміни розміру і порівнює його з розміром в кінці розміру, якщо розмір більший або менший за маржу ( напр., 1000) потім він перезавантажується.
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;
}
Відповідь Марка Коулмана, безумовно, набагато краща, ніж обрана відповідь, але якщо ви хочете уникнути глобальної змінної для ідентифікатора тайм-ауту ( doit
змінна у відповіді Марка), ви можете зробити одне з наступного:
(1) Використовуйте вираз функції, що негайно викликається (IIFE), щоб створити закриття.
$(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) Використовуйте властивість функції обробника подій.
$(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);
});
Я написав функцію обгортки для нігтів самостійно ...
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);
});
};
Ось використання:
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(){
//...
});
Ну, наскільки віконний менеджер стурбований, кожна подія зміни розміру є його власне повідомлення, з виразним початком і кінцем, так що технічно, кожен раз при зміні розміру вікна, то це кінець.
Сказавши це, можливо, ви хочете встановити затримку вашого продовження? Ось приклад.
var t = -1;
function doResize()
{
document.write('resize');
}
$(document).ready(function(){
$(window).resize(function(){
clearTimeout(t);
t = setTimeout(doResize, 1000);
});
});
Ось ДУЖЕ простий скрипт для запуску події "resizestart" і "resizeend" на об'єкті вікна.
Немає необхідності гнатися з датами та часом.
d
Змінна являє число мілісекунд між подіями зміни розміру перед запуском кінцевого зміни розміру події, ви можете грати з цим , щоб змінити , наскільки чутливими до кінця події.
Для прослуховування цих подій все, що вам потрібно зробити:
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));
Це те, що я використовую для затримки повторних дій, його можна викликати в декількох місцях у вашому коді:
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);
};
};
Використання:
$(window).resize(function () {
debounce(function() {
//...
}, 500);
});
оскільки обрана відповідь насправді не працює .. і якщо ви не використовуєте jquery, тут проста функція дросельної заслінки з прикладом того, як її використовувати із зміною розміру вікна
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();
}
це працювало для мене, оскільки я не хотів використовувати жодні плагіни.
$(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();
});
У вікні повторного розміру викликайте "setFn", який отримує ширину вікна і зберігає як "originalWindowSize". Потім виберіть "checkFn", який через 500 мс (або ваш уподобання) отримує поточний розмір вікна, і порівнює оригінал із поточним, якщо вони не однакові, то вікно все ще змінюється за розміром. Не забудьте видалити консольні повідомлення у виробництві, і (необов’язково) можна зробити "setFn" самовиконанням.
var resizeTimer;
$( window ).resize(function() {
if(resizeTimer){
clearTimeout(resizeTimer);
}
resizeTimer = setTimeout(function() {
//your code here
resizeTimer = null;
}, 200);
});
Це працювало на те, що я намагався зробити в хромі. Це не призведе до зворотного виклику до 200 мс після останньої події зміни розміру.
Краща альтернатива також створена мною тут: https://stackoverflow.com/a/23692008/2829600 (підтримує "видалити функції")
Я написав цю просту функцію для обробки затримки у виконанні, корисну всередині jQuery .scroll () та .resize (), тож callback_f буде працювати лише один раз для певного рядка 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 ... }); });
? Досить чистий код інакше. Дякую, що поділились. :)
Я реалізував функцію, яка запускає дві події на елементі DOM користувача:
Код:
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...
}
Я не знаю, чи працює мій код для інших, але для мене це справді чудова робота. Цю ідею я отримав, аналізуючи код Долана Антенкучі, оскільки його версія для мене не працює, і я дуже сподіваюся, що комусь вона буде корисна.
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);
}
Я написав функцію, яка передає функцію під час завершення будь-якої події зміни розміру. Він використовує інтервал, щоб розмір навіть не постійно створював події очікування. Це дозволяє йому виконувати незалежно від події зміни розміру, крім запису журналу, який слід видалити у виробництві.
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()
щоб воно виконувалося лише після того, як буде зроблено всі зміни розміру, а не знову і знову?