Vì vậy, tôi hiện đang sử dụng một cái gì đó như:
$(window).resize(function(){resizedw();});
Nhưng điều này được gọi nhiều lần trong khi quá trình thay đổi kích thước diễn ra. Có thể bắt một sự kiện khi nó kết thúc?
Vì vậy, tôi hiện đang sử dụng một cái gì đó như:
$(window).resize(function(){resizedw();});
Nhưng điều này được gọi nhiều lần trong khi quá trình thay đổi kích thước diễn ra. Có thể bắt một sự kiện khi nó kết thúc?
Câu trả lời:
Tôi đã may mắn với lời giới thiệu sau: http://forum.jquery.com/topic/the-resizeend-event
Đây là mã để bạn không phải tìm hiểu qua liên kết & nguồn của bài đăng của anh ấy:
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');
}
}
Cảm ơn sime.vidas cho mã!
new Date(-1E12)
- tức là JSLint cảnh báo về việc sử dụng 00
.
rtime: Date; .... if (+new Date() - +rtime < delta)
và trong chức năng resizeend nên được chức năng mũi tên như thế này resizeend=()=>
. Bởi vì trong hàm resizeend, this
tham chiếu đến đối tượng cửa sổ.
Bạn có thể sử dụng setTimeout()
vàclearTimeout()
function resizedw(){
// Haven't resized in 100ms!
}
var doit;
window.onresize = function(){
clearTimeout(doit);
doit = setTimeout(resizedw, 100);
};
Mã ví dụ trên jsfiddle .
$(document)
khả năng phát hiện chuột sẽ bị giới hạn ở người dùng chạy Microsoft Windows và các phiên bản dễ bị tổn thương của Internet Explorer: iedirtheak.spider.io/demo
Đây là mã mà tôi viết theo câu trả lời của @Mark Coleman:
$(window).resize(function() {
clearTimeout(window.resizedFinished);
window.resizedFinished = setTimeout(function(){
console.log('Resized finished.');
}, 250);
});
Cảm ơn Mark!
resizeTimer
là biến toàn cục, nghĩa là nó được định nghĩa không có window
, vì vậy nó giống hệt như ở đây, chỉ có ví dụ này là tốt hơn vì bạn không cần xác định biến bên ngoài. và cũng có ý nghĩa khi thêm biến này vào window
đối tượng vì đó là Đối tượng mà trình lắng nghe sự kiện được liên kết.
Internet Explorer cung cấp một sự kiện thay đổi kích thước . Các trình duyệt khác sẽ kích hoạt sự kiện thay đổi kích thước nhiều lần trong khi bạn thay đổi kích thước.
Có những câu trả lời tuyệt vời khác ở đây chỉ ra cách sử dụng setTimeout và .thrption ,Các phương thức .debounce từ lodash và undererscore, vì vậy tôi sẽ đề cập đến plugin jQuery gỡ rối tiết kiệm của Ben Alman để thực hiện những gì bạn đang theo đuổi.
Giả sử bạn có chức năng này mà bạn muốn kích hoạt sau khi thay đổi kích thước:
function onResize() {
console.log("Resize just happened!");
};
Ví dụ về bướm ga
Trong ví dụ sau, onResize()
sẽ chỉ được gọi một lần sau mỗi 250 mili giây trong khi thay đổi kích thước cửa sổ.
$(window).resize( $.throttle( 250, onResize) );
Ví dụ gỡ lỗi
Trong ví dụ sau, onResize()
sẽ chỉ được gọi một lần ở cuối hành động thay đổi kích thước cửa sổ. Điều này đạt được kết quả tương tự mà @Mark trình bày trong câu trả lời của mình.
$(window).resize( $.debounce( 250, onResize) );
Có một giải pháp tinh tế khi sử dụng Underscore.js Vì vậy, nếu bạn đang sử dụng nó trong dự án của mình, bạn có thể thực hiện như sau -
$( window ).resize( _.debounce( resizedw, 500 ) );
Điều này là đủ :) Nhưng, nếu bạn muốn đọc thêm về điều đó, bạn có thể kiểm tra bài đăng trên blog của tôi - http://rifatnabi.com/post/detect-end-of-jquery-resize-event-USE-underscore -debounce ( deadlink )
lodash
cũng cung cấp điều này
Một giải pháp là mở rộng jQuery với một hàm, ví dụ: 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));
});
};
Sử dụng mẫu:
$(window).resized(myHandler, 300);
Bạn có thể lưu trữ id tham chiếu cho bất kỳ setInterval hoặc setTimeout nào. Như thế này:
var loop = setInterval(func, 30);
// some time later clear the interval
clearInterval(loop);
Để làm điều này mà không có biến "toàn cầu", bạn có thể thêm một biến cục bộ vào chính hàm đó. Ví dụ:
$(window).resize(function() {
clearTimeout(this.id);
this.id = setTimeout(doneResizing, 500);
});
function doneResizing(){
$("body").append("<br/>done!");
}
Bạn có thể sử dụng setTimeout()
và clearTimeout()
kết hợp với jQuery.data
:
$(window).resize(function() {
clearTimeout($.data(this, 'resizeTimer'));
$.data(this, 'resizeTimer', setTimeout(function() {
//do something
alert("Haven't resized in 200ms!");
}, 200));
});
Cập nhật
Tôi đã viết một phần mở rộng để nâng cao trình xử lý mặc định on
(& bind
) của jQuery. Nó gắn một hàm xử lý sự kiện cho một hoặc nhiều sự kiện cho các phần tử được chọn nếu sự kiện không được kích hoạt trong một khoảng nhất định. Điều này hữu ích nếu bạn chỉ muốn thực hiện một cuộc gọi lại sau khi trì hoãn, như sự kiện thay đổi kích thước, hoặc nếu không.
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));
Sử dụng nó như bất kỳ trình xử lý nào khác on
hoặc bind
ngoại lệ, ngoại trừ việc bạn có thể truyền một tham số phụ như cuối cùng:
$(window).on('resize', function(e) {
console.log(e.type + '-event was 200ms not triggered');
}, 200);
Có một phương pháp đơn giản hơn nhiều để thực thi một hàm ở cuối thay đổi kích thước so với tính thời gian delta giữa hai cuộc gọi, chỉ cần thực hiện như sau:
var resizeId;
$(window).resize(function() {
clearTimeout(resizeId);
resizeId = setTimeout(resizedEnded, 500);
});
function resizedEnded(){
...
}
Và tương đương với Angular2 :
private resizeId;
@HostListener('window:resize', ['$event'])
onResized(event: Event) {
clearTimeout(this.resizeId);
this.resizeId = setTimeout(() => {
// Your callback method here.
}, 500);
}
Đối với phương pháp góc, sử dụng () => { }
ký hiệu trong setTimeout
để bảo toàn phạm vi, nếu không bạn sẽ không thể thực hiện bất kỳ lệnh gọi hoặc sử dụng chức năng nào this
.
Đây là một sửa đổi cho mã của Dolan ở trên, tôi đã thêm một tính năng kiểm tra kích thước cửa sổ khi bắt đầu thay đổi kích thước và so sánh nó với kích thước ở cuối thay đổi kích thước, nếu kích thước lớn hơn hoặc nhỏ hơn lề ( ví dụ 1000) sau đó nó tải lại.
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;
}
Câu trả lời của Mark Coleman chắc chắn tốt hơn nhiều so với câu trả lời đã chọn, nhưng nếu bạn muốn tránh biến toàn cục cho ID hết thời gian ( doit
biến trong câu trả lời của Mark), bạn có thể thực hiện một trong các cách sau:
(1) Sử dụng biểu thức hàm được gọi ngay lập tức (IIFE) để tạo một bao đóng.
$(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) Sử dụng một thuộc tính của chức năng xử lý sự kiện.
$(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);
});
tôi đã tự mình viết một hàm bao bọc 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);
});
};
Đây là cách sử dụng:
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(){
//...
});
Vâng, theo như trình quản lý cửa sổ, mỗi sự kiện thay đổi kích thước là thông điệp riêng của nó, với một khởi đầu và kết thúc riêng biệt, vì vậy về mặt kỹ thuật, mỗi khi cửa sổ được thay đổi kích thước, đó là kết thúc.
Có nói rằng, có lẽ bạn muốn đặt một sự chậm trễ để tiếp tục của bạn? Đây là một ví dụ.
var t = -1;
function doResize()
{
document.write('resize');
}
$(document).ready(function(){
$(window).resize(function(){
clearTimeout(t);
t = setTimeout(doResize, 1000);
});
});
Đây là kịch bản RẤT đơn giản để kích hoạt cả sự kiện 'resizestart' và 'resizeend' trên đối tượng cửa sổ.
Không cần phải loay hoay với ngày và thời gian.
Các d
biến đại diện cho số mili giây giữa các sự kiện thay đổi kích thước trước khi kích hoạt các sự kiện thay đổi kích thước kết thúc, bạn có thể chơi với điều này để thay đổi cách nhạy cảm sự kiện cuối cùng là.
Để nghe những sự kiện này, tất cả những gì bạn cần làm là:
resizestart: $(window).on('resizestart', function(event){console.log('Resize Start!');});
tiếp tục:
$(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));
Đây là những gì tôi sử dụng để trì hoãn các hành động lặp đi lặp lại, nó có thể được gọi ở nhiều nơi trong mã của bạn:
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);
};
};
Sử dụng:
$(window).resize(function () {
debounce(function() {
//...
}, 500);
});
vì câu trả lời được chọn không thực sự hoạt động .. và nếu bạn không sử dụng jquery thì đây là một chức năng điều tiết đơn giản với một ví dụ về cách sử dụng nó với thay đổi kích thước cửa sổ
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();
}
điều này làm việc cho tôi vì tôi không muốn sử dụng bất kỳ plugin nào.
$(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();
});
Trên cửa sổ kích thước lại gọi "setFn" có chiều rộng của cửa sổ và lưu dưới dạng "originalWindowSize". Sau đó gọi "checkFn" mà sau 500ms (hoặc tùy chọn của bạn) sẽ có kích thước cửa sổ hiện tại và so sánh bản gốc với hiện tại, nếu chúng không giống nhau, thì cửa sổ vẫn được đặt lại kích thước. Đừng quên xóa các thông báo bảng điều khiển trong sản xuất và (tùy chọn) có thể tự thực hiện "setFn".
var resizeTimer;
$( window ).resize(function() {
if(resizeTimer){
clearTimeout(resizeTimer);
}
resizeTimer = setTimeout(function() {
//your code here
resizeTimer = null;
}, 200);
});
Điều này làm việc cho những gì tôi đã cố gắng để làm trong chrome. Điều này sẽ không kích hoạt cuộc gọi lại cho đến 200ms sau sự kiện thay đổi kích thước cuối cùng.
Thay thế tốt hơn cũng do tôi tạo ra là ở đây: https://stackoverflow.com/a/23692008/2829600 (hỗ trợ "xóa chức năng")
Tôi đã viết hàm đơn giản này để xử lý độ trễ khi thực thi, hữu ích bên trong jQuery .scroll () và .resize () Vì vậy, callback_f sẽ chỉ chạy một lần cho chuỗi id cụ thể.
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 ... }); });
? Mã khá sạch khác. Cám ơn vì đã chia sẻ. :)
Tôi đã triển khai chức năng theo dõi hai sự kiện trên phần tử DOM của người dùng:
Mã số:
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...
}
Tôi không biết là mã của tôi làm việc cho người khác nhưng nó thực sự làm một công việc tuyệt vời cho tôi. Tôi có ý tưởng này bằng cách phân tích mã Dolan Antenucci vì phiên bản của anh ấy không phù hợp với tôi và tôi thực sự hy vọng nó sẽ hữu ích cho ai đó.
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);
}
Tôi đã viết một hàm vượt qua một hàm khi được bọc trong bất kỳ sự kiện thay đổi kích thước nào. Nó sử dụng một khoảng thời gian để thay đổi kích thước thậm chí không liên tục tạo ra các sự kiện hết thời gian. Điều này cho phép nó thực hiện độc lập với sự kiện thay đổi kích thước khác với mục nhật ký cần được loại bỏ trong sản xuất.
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()
để nó chỉ thực hiện sau khi thay đổi kích thước xong và không lặp đi lặp lại?