Jadi saya saat ini menggunakan sesuatu seperti:
$(window).resize(function(){resizedw();});
Tapi ini dipanggil berkali-kali saat proses mengubah ukuran berlangsung. Apakah mungkin untuk menangkap suatu peristiwa ketika itu berakhir?
Jadi saya saat ini menggunakan sesuatu seperti:
$(window).resize(function(){resizedw();});
Tapi ini dipanggil berkali-kali saat proses mengubah ukuran berlangsung. Apakah mungkin untuk menangkap suatu peristiwa ketika itu berakhir?
Jawaban:
Saya beruntung dengan rekomendasi berikut: http://forum.jquery.com/topic/the-resizeend-event
Inilah kodenya sehingga Anda tidak perlu menggali melalui tautan & sumber posnya:
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');
}
}
Terima kasih sime.vidas untuk kodenya!
new Date(-1E12)
- yaitu JSLint memperingatkan tentang penggunaan 00
.
rtime: Date; .... if (+new Date() - +rtime < delta)
dan dalam fungsi resizeend naskah harus fungsi panah seperti ini resizeend=()=>
. Karena dalam fungsi resizeend, this
merujuk ke objek jendela.
Anda bisa menggunakan setTimeout()
danclearTimeout()
function resizedw(){
// Haven't resized in 100ms!
}
var doit;
window.onresize = function(){
clearTimeout(doit);
doit = setTimeout(resizedw, 100);
};
Contoh kode pada jsfiddle .
Ini adalah kode yang saya tulis sesuai dengan jawaban @Mark Coleman:
$(window).resize(function() {
clearTimeout(window.resizedFinished);
window.resizedFinished = setTimeout(function(){
console.log('Resized finished.');
}, 250);
});
Mark terima kasih!
resizeTimer
adalah variabel global, artinya tidak didefinisikan window
, jadi persis sama dengan di sini, hanya contoh ini yang lebih baik karena Anda tidak perlu mendefinisikan variabel secara eksternal. dan masuk akal untuk menambahkan variabel ini ke window
objek karena itu adalah objek yang diikat oleh pendengar acara.
Internet Explorer menyediakan acara pengubahan ukuran . Peramban lain akan memicu acara pengubahan ukuran berkali-kali saat Anda mengubah ukuran.
Ada jawaban hebat lainnya di sini yang menunjukkan cara menggunakan setTimeout dan .throttle ,.debounce metode dari lodash dan garis bawah, jadi saya akan menyebutkan plugin jQuery throttle-debounce dari Ben Alman yang memenuhi apa yang Anda cari.
Misalkan Anda memiliki fungsi ini yang ingin Anda picu setelah mengubah ukuran:
function onResize() {
console.log("Resize just happened!");
};
Contoh Throttle
Dalam contoh berikut, onResize()
hanya akan dipanggil sekali setiap 250 milidetik selama ukuran jendela.
$(window).resize( $.throttle( 250, onResize) );
Contoh Debounce
Pada contoh berikut, onResize()
hanya akan dipanggil sekali pada akhir tindakan mengubah ukuran jendela. Ini mencapai hasil yang sama dengan yang disajikan oleh @Mark dalam jawabannya.
$(window).resize( $.debounce( 250, onResize) );
Ada solusi elegan menggunakan Underscore.js Jadi, jika Anda menggunakannya dalam proyek Anda, Anda dapat melakukan hal berikut -
$( window ).resize( _.debounce( resizedw, 500 ) );
Ini sudah cukup :) Tapi, Jika Anda tertarik untuk membaca lebih lanjut tentang itu, Anda dapat memeriksa posting blog saya - http://rifatnabi.com/post/detect-end-of-jquery-resize-event-using-underscore -debounce (deadlink)
lodash
juga menyediakan ini
Salah satu solusinya adalah memperluas jQuery dengan suatu fungsi, misalnya: 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));
});
};
Penggunaan sampel:
$(window).resized(myHandler, 300);
Anda dapat menyimpan id referensi ke setInterval atau setTimeout. Seperti ini:
var loop = setInterval(func, 30);
// some time later clear the interval
clearInterval(loop);
Untuk melakukan ini tanpa variabel "global" Anda dapat menambahkan variabel lokal ke fungsi itu sendiri. Ex:
$(window).resize(function() {
clearTimeout(this.id);
this.id = setTimeout(doneResizing, 500);
});
function doneResizing(){
$("body").append("<br/>done!");
}
Anda dapat menggunakan setTimeout()
dan clearTimeout()
bersamaan dengan jQuery.data
:
$(window).resize(function() {
clearTimeout($.data(this, 'resizeTimer'));
$.data(this, 'resizeTimer', setTimeout(function() {
//do something
alert("Haven't resized in 200ms!");
}, 200));
});
Memperbarui
Saya menulis ekstensi untuk meningkatkan default on
(& bind
) -event-handler jQuery . Ini melampirkan fungsi event handler untuk satu atau lebih peristiwa ke elemen yang dipilih jika acara tidak dipicu untuk interval yang diberikan. Ini berguna jika Anda ingin memecat panggilan balik hanya setelah penundaan, seperti acara pengubahan ukuran, atau yang lain.
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));
Gunakan itu seperti penangan lain on
atau bind
-event, kecuali bahwa Anda dapat melewatkan parameter tambahan sebagai yang terakhir:
$(window).on('resize', function(e) {
console.log(e.type + '-event was 200ms not triggered');
}, 200);
Ada metode yang jauh lebih sederhana untuk menjalankan fungsi di akhir pengubahan ukuran daripada menghitung waktu delta di antara dua panggilan, lakukan saja seperti ini:
var resizeId;
$(window).resize(function() {
clearTimeout(resizeId);
resizeId = setTimeout(resizedEnded, 500);
});
function resizedEnded(){
...
}
Dan yang setara untuk Angular2 :
private resizeId;
@HostListener('window:resize', ['$event'])
onResized(event: Event) {
clearTimeout(this.resizeId);
this.resizeId = setTimeout(() => {
// Your callback method here.
}, 500);
}
Untuk metode sudut, gunakan () => { }
notasi dalam setTimeout
untuk mempertahankan cakupan, jika tidak, Anda tidak akan dapat membuat panggilan fungsi atau penggunaan this
.
Ini adalah modifikasi dari kode Dolan di atas, saya telah menambahkan fitur yang memeriksa ukuran jendela di awal ukuran dan membandingkannya dengan ukuran di akhir ukuran, jika ukurannya lebih besar atau lebih kecil dari margin ( mis. 1000) lalu dimuat ulang.
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;
}
Jawaban Mark Coleman tentu jauh lebih baik daripada jawaban yang dipilih, tetapi jika Anda ingin menghindari variabel global untuk ID timeout ( doit
variabel dalam jawaban Mark), Anda dapat melakukan salah satu dari yang berikut:
(1) Gunakan ekspresi fungsi yang segera dipanggil (IIFE) untuk membuat penutupan.
$(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) Gunakan properti fungsi event handler.
$(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);
});
saya menulis fungsi litte wrapper sendiri ...
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);
});
};
Ini adalah penggunaannya:
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(){
//...
});
Nah, sejauh menyangkut window manager, masing-masing event resize adalah pesannya sendiri, dengan awal dan akhir yang berbeda, jadi secara teknis, setiap kali window diubah ukurannya, itu adalah akhirnya.
Karena itu, mungkin Anda ingin mengatur kelanjutan Anda? Ini sebuah contoh.
var t = -1;
function doResize()
{
document.write('resize');
}
$(document).ready(function(){
$(window).resize(function(){
clearTimeout(t);
t = setTimeout(doResize, 1000);
});
});
Berikut ini skrip SANGAT sederhana untuk memicu acara 'resizestart' dan 'resizeend' pada objek jendela.
Tidak perlu berkutat dengan tanggal dan waktu.
The d
variabel mewakili jumlah milidetik antara peristiwa mengubah ukuran sebelum memicu peristiwa mengubah ukuran akhir, Anda dapat bermain dengan ini untuk mengubah seberapa sensitif acara akhirnya adalah.
Untuk mendengarkan acara ini, yang perlu Anda lakukan adalah:
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));
Ini yang saya gunakan untuk menunda tindakan berulang, bisa dipanggil di banyak tempat dalam kode Anda:
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);
};
};
Pemakaian:
$(window).resize(function () {
debounce(function() {
//...
}, 500);
});
karena jawaban yang dipilih tidak benar-benar berfungsi .. dan jika Anda tidak menggunakan jquery di sini adalah fungsi throttle sederhana dengan contoh cara menggunakannya dengan mengubah ukuran jendela
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();
}
ini bekerja untuk saya karena saya tidak ingin menggunakan plugin apa pun.
$(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();
});
Di jendela kembali ukuran memanggil "setFn" yang mendapat lebar jendela dan simpan sebagai "originalWindowSize". Kemudian aktifkan "checkFn" yang setelah 500 ms (atau preferensi Anda) mendapatkan ukuran jendela saat ini, dan membandingkan yang asli dengan saat ini, jika tidak sama, maka jendela tersebut masih berukuran ulang. Jangan lupa untuk menghapus pesan konsol dalam produksi, dan (opsional) dapat membuat "setFn" dieksekusi sendiri.
var resizeTimer;
$( window ).resize(function() {
if(resizeTimer){
clearTimeout(resizeTimer);
}
resizeTimer = setTimeout(function() {
//your code here
resizeTimer = null;
}, 200);
});
Ini bekerja untuk apa yang saya coba lakukan di chrome. Ini tidak akan memecat panggilan balik hingga 200 ms setelah acara pengubahan ukuran terakhir.
Alternatif yang lebih baik juga dibuat oleh saya ada di sini: https://stackoverflow.com/a/23692008/2829600 (mendukung "hapus fungsi")
Saya menulis fungsi sederhana ini untuk menangani penundaan eksekusi, berguna di dalam jQuery .scroll () dan .resize () Jadi, callback_f hanya akan berjalan sekali untuk string id tertentu.
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 ... }); });
? Kode yang cukup bersih sebaliknya. Terima kasih telah berbagi. :)
Saya mengimplementasikan fungsi yang memicu dua peristiwa pada elemen DOM pengguna:
Kode:
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...
}
Saya tidak tahu apakah kode saya berfungsi untuk orang lain, tetapi benar-benar melakukan pekerjaan yang baik untuk saya. Saya mendapat ide ini dengan menganalisis kode Dolan Antenucci karena versinya tidak berfungsi untuk saya dan saya sangat berharap ini akan membantu seseorang.
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);
}
Saya menulis sebuah fungsi yang melewati suatu fungsi ketika dibungkus dalam setiap peristiwa pengubahan ukuran. Ini menggunakan interval sehingga mengubah ukuran bahkan tidak terus-menerus membuat acara timeout. Hal ini memungkinkannya untuk melakukan secara independen dari peristiwa pengubahan ukuran selain dari entri log yang harus dihapus dalam produksi.
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()
sehingga hanya dijalankan setelah semua pengubahan ukuran dilakukan dan tidak berulang?