JavaScript penceresi yeniden boyutlandırma etkinliği


Yanıtlar:


640

jQuery sadece standart resizeDOM olayını tamamlıyor, örn.

window.onresize = function(event) {
    ...
};

jQuery olabilir boyutlandırma olay tüm tarayıcılarda tutarlı kovuluyor sağlamak için bazı işler yapmak, ancak tarayıcılardan herhangi farklılık olmadığından emin değilim, ama ben Firefox, Safari ve IE test etmek öneririm.


226
Bu yöntemle ilgili potansiyel bir sorun, etkinliği geçersiz kıldığınızdır ve bu nedenle bir etkinliğe birden fazla eylem ekleyemezsiniz. AddEventListener / attachEvent combo, javascript'inizin sayfada yürütülmekte olan diğer komut dosyalarıyla dostça oynatılmasını sağlamanın en iyi yoludur.
MyItchyChin

4
var onresize = window.onresize; window.onresize = function (event) {if (typeof onresize === 'function') onresize (); / ** ... * /}
SubOne

230
window.addEventListener('resize', function(){}, true);
WebWanderer

16
@SubOne, bunu asla yapmamak için mükemmel bir örnek.
Eugene Pankov

28
ECMAScript 6 : window.onresize = () => { /* code */ };or better:window.addEventListener('resize', () => { /* code */ });
Derk Jan Speelman

561

Öncelikle, addEventListeneryöntem yukarıdaki yorumlarda belirtildiğini biliyorum , ancak herhangi bir kod görmedim. Tercih edilen yaklaşım olduğu için burada:

window.addEventListener('resize', function(event){
  // do stuff here
});

İşte çalışan bir örnek .


63
Bu en basit cevaptır.
jacoviza

7
En iyi cevap gibi geliyor çünkü window.onresize etkinliğinin üzerine yazmıyorsunuz :-)
James Harrington

27
Birçok kişi bu örnekte yaptığınız gibi anonim olay dinleyicileri ekliyor, ancak bu gerçekten iyi bir uygulama değil, çünkü bu yaklaşım bu dinleyicileri daha sonra kaldırmayı imkansız hale getiriyor . Web sayfaları zaten kısa ömürlü olduğu için bu bir sorun değildi, ancak AJAX ve RIAs ve SPA'ların bu gün ve çağında bir haline geliyor. Olay dinleyicilerinin yaşam döngüsünü yönetmek için bir yola ihtiyacımız var. Bu nedenle, dinleyici işlevini ayrı bir işlevde hesaba katmak daha iyi olur, böylece daha sonra kaldırılabilir removeEventListener.
Stijn de Witt

6
neden herkes kabartmadan böyle cevap
veremez

2
Sanırım burada hem Stijn de Witt'in hem de quemeful'ın cevapları için gerçek var. Bazen olay dinleyicilerini kaldırmayı önemsersiniz, ancak istemiyorsanız, yukarıdaki örnekte olduğu gibi tüm bu ekstra kodları eklemek gereksizdir ve hem şişirilebilir hem de daha az okunabilir olabilir. Bence, dinleyiciyi kaldırmanız için bir neden öngörmüyorsanız, bu yaklaşım en iyi çözümdür. Gerekirse daha sonra istediğiniz zaman yeniden yazabilirsiniz. Deneyimlerime göre, bu ihtiyaçlar sadece belirli durumlarda ortaya çıkar.
cazort

525

Asla window.onresize işlevini geçersiz kılmayın.

Bunun yerine, nesneye veya öğeye Olay Dinleyici eklemek için bir işlev oluşturun. Bu, dinleyicilerin çalışmadığını denetler ve kapatır, daha sonra nesnenin işlevini son çare olarak geçersiz kılar. Bu, jQuery gibi kütüphanelerde kullanılan tercih edilen yöntemdir.

object: öğe veya pencere nesnesi
type: yeniden boyutlandır, kaydırma (olay türü)
callback: işlev başvurusu

var addEvent = function(object, type, callback) {
    if (object == null || typeof(object) == 'undefined') return;
    if (object.addEventListener) {
        object.addEventListener(type, callback, false);
    } else if (object.attachEvent) {
        object.attachEvent("on" + type, callback);
    } else {
        object["on"+type] = callback;
    }
};

O zaman kullanım şöyle:

addEvent(window, "resize", function_reference);

veya anonim bir işlevle:

addEvent(window, "resize", function(event) {
  console.log('resized');
});

100
Bu kabul edilen cevap olmalıydı. Onresize geçersiz kılma sadece kötü bir uygulamadır.
Tiberiu-Ionuț Stan

8
hah, tüm ekstra null kontroller neler? IE 4.5 falan çalışıyorum?
FlavorScape

1
Ve pencere yeniden boyutlandırma olaylarını almak için bu işlevi nasıl çağırdığımı merak ediyorsunuz? İşte böyle: addEvent (window, "resize", function_reference); :)
oabarca

6
IE 11'den itibaren attachEventartık desteklenmediğini unutmayın. Gelecek için tercih edilen yol addEventListener.
Luke

6
Dikkatli ol elem == undefined. "Tanımlanmamış" ın yerel olarak başka bir şey olarak tanımlanması (olası olmasa da) mümkündür. stackoverflow.com/questions/8175673/…
Luke

32

Yeniden boyutlandırma olayı, yeniden boyutlandırdığımız gibi sürekli tetiklendiğinden asla doğrudan kullanılmamalıdır.

Fazla aramaları azaltmak için bir geri dönme işlevi kullanın.

window.addEventListener('resize',debounce(handler, delay, immediate),false);

Burada, ağ etrafında yüzen ortak bir geri dönme var, ancak daha gelişmiş olanları lodash'da featuerd olarak arayın.

const debounce = (func, wait, immediate) => {
    var timeout;
    return () => {
        const context = this, args = arguments;
        const later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        const callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};

Bu şekilde kullanılabilir ...

window.addEventListener('resize', debounce(() => console.log('hello'),
200, false), false);

Asla her 200 ms'de bir defadan fazla ateş etmeyecektir.

Mobil yönlendirme değişiklikleri için şunları kullanın:

window.addEventListener('orientationchange', () => console.log('hello'), false);

İşte bununla ilgilenmek için bir araya getirdiğim küçük bir kütüphane .


Ben debounce (daha önce bu şekilde zaman aşımlarını kullanmaya direnmiş olmama rağmen artık paha biçilemez bir kavram / işlev gibi görünüyor) hakkındaki bilgileri takdir ediyorum, lodash (kişisel olarak ikna olmama rağmen) ve addEvent'in yedek olarak kullanılıp kullanılmayacağı konusundaki belirsizliği çözme to addEventListener (yalnızca eski yanıtlar bu
konudaki

5
FYI, ES6 ok işlevi gösterimini kullandığınız için, değişkenin kapsamı artık kullanılamadığından iç işlevin (...arguments) => {...}(veya ...argsdaha az karışıklık için) olması gerekir arguments.
coderatchet

Bu pasajı kodum değil, sadece bir örnek olarak tamamen biliyorum.
frontsideup

Büyük cevap, yeniden boyutlandırma ile mükemmel konuların ele alınması gerekiyor! Sönümleme bir seçenektir, diğeri basit bir kısmadır ("adımlarınızda yeniden boyutlandırmak için kullanıcı arayüzünüze ihtiyacınız varsa gitmek için bir yol olabilir). Örnekler için bencentra.com/code/2015/02/27/optimizing-window-resize.html adresine bakın
Robin Métral

24

2018+ için çözüm:

ResizeObserver kullanmalısınız . resizeEtkinliği kullanmaktan çok daha iyi performansa sahip tarayıcıya özgü bir çözümdür . Ayrıca, olayı sadece değil document, keyfi olarak da destekler elements.

var ro = new ResizeObserver( entries => {
  for (let entry of entries) {
    const cr = entry.contentRect;
    console.log('Element:', entry.target);
    console.log(`Element size: ${cr.width}px x ${cr.height}px`);
    console.log(`Element padding: ${cr.top}px ; ${cr.left}px`);
  }
});

// Observe one or multiple elements
ro.observe(someElement);

Şu anda Firefox, Chrome ve Safari destekliyor . Diğer (ve daha eski) tarayıcılar için bir çoklu dolgu kullanmanız gerekir .


2020 imo hala en iyi cevap
Jesse Reza Khorasanee


16

@Alex V tarafından doğru cevabın verildiğine inanıyorum, ancak cevap beş yıldan daha eski olduğu için biraz modernizasyon gerektiriyor.

İki ana konu vardır:

  1. Asla objectparametre adı olarak kullanmayın . Korunmuş bir kelimedir. Bununla birlikte, @Alex V'nin sağlanan işlevi çalışmayacaktır strict mode.

  2. addEvent@Alex V tarafından temin edilmekte olan işlev dönmez event objectise addEventListeneryöntemi kullanılır. Buna addEventizin vermek için işleve başka bir parametre eklenmelidir .

NOT: Yeni parametre, addEventbu yeni işlev sürümüne geçişin bu işleve yapılan önceki çağrıları bozmaması için isteğe bağlı hale getirilmiştir. Tüm eski kullanımlar desteklenecektir.

İşte addEventbu değişikliklerle güncellenmiş fonksiyon:

/*
    function: addEvent

    @param: obj         (Object)(Required)

        -   The object which you wish
            to attach your event to.

    @param: type        (String)(Required)

        -   The type of event you
            wish to establish.

    @param: callback    (Function)(Required)

        -   The method you wish
            to be called by your
            event listener.

    @param: eventReturn (Boolean)(Optional)

        -   Whether you want the
            event object returned
            to your callback method.
*/
var addEvent = function(obj, type, callback, eventReturn)
{
    if(obj == null || typeof obj === 'undefined')
        return;

    if(obj.addEventListener)
        obj.addEventListener(type, callback, eventReturn ? true : false);
    else if(obj.attachEvent)
        obj.attachEvent("on" + type, callback);
    else
        obj["on" + type] = callback;
};

Yeni addEventişleve örnek bir çağrı :

var watch = function(evt)
{
    /*
        Older browser versions may return evt.srcElement
        Newer browser versions should return evt.currentTarget
    */
    var dimensions = {
        height: (evt.srcElement || evt.currentTarget).innerHeight,
        width: (evt.srcElement || evt.currentTarget).innerWidth
    };
};

addEvent(window, 'resize', watch, true);

AttachEvent'in 2017'de artık geçerli olmadığını iddia ediyorum.
Vlad Nicula

@VladNicula katılıyorum, ama bu cevap iki yaşında.
WebWanderer

12

Http://mbccs.blogspot.com/2007/11/fixing-window-resize-event-in-ie.html adresindeki blog yayınımı referans aldığınız için teşekkür ederiz .

Standart pencere yeniden boyutlandırma etkinliğine bağlanabilirken, IE'de etkinliğin her X için bir kez ve her Y ekseni hareketi için bir kez tetiklendiğini görürsünüz. oluşturma yoğun bir işse siteniz üzerindeki etkisi.

Metodum, kullanıcı pencereyi yeniden boyutlandırmayı bitirinceye kadar olayın kodunuza kadar kabarmaması için, sonraki olaylarda iptal edilen kısa bir zaman aşımı içerir.


7
window.onresize = function() {
    // your code
};

22
Yukarıdaki yorumların çoğunun söylediği gibi, onresize işlevinin üzerine yazmamak en iyisidir; bunun yerine yeni bir etkinlik ekleyin. Jondlm'in cevabına bakınız.
Luke

6

Aşağıdaki blog yayını sizin için yararlı olabilir: IE'de pencere yeniden boyutlandırma olayını düzeltme

Bu kodu sağlar:

Sys.Application.add_load(function(sender, args) {
    $addHandler(window, 'resize', window_resize);
});

var resizeTimeoutId;

function window_resize(e) {
     window.clearTimeout(resizeTimeoutId);
     resizeTimeoutId = window.setTimeout('doResizeCode();', 10);
}

6
Bu yalnızca ASP.NET uygulamaları için geçerlidir
Evgeny Gorb

2

Yukarıda belirtilen çözümler, tek yapmanız gereken yalnızca pencereyi ve pencereyi yeniden boyutlandırmaksa işe yarayacaktır. Ancak, yeniden boyutlandırmanın alt öğelere yayılmasını istiyorsanız, etkinliği kendiniz yaymanız gerekir. İşte bunu yapmak için bazı örnek kod:

window.addEventListener("resize", function () {
  var recResizeElement = function (root) {
    Array.prototype.forEach.call(root.childNodes, function (el) {

      var resizeEvent = document.createEvent("HTMLEvents");
      resizeEvent.initEvent("resize", false, true);
      var propagate = el.dispatchEvent(resizeEvent);

      if (propagate)
        recResizeElement(el);
    });
  };
  recResizeElement(document.body);
});

Bir alt öğenin arayabileceğini unutmayın

 event.preventDefault();

resize olayının ilk Arg'si olarak iletilen olay nesnesinde. Örneğin:

var child1 = document.getElementById("child1");
child1.addEventListener("resize", function (event) {
  ...
  event.preventDefault();
});

1
<script language="javascript">
    window.onresize = function() {
    document.getElementById('ctl00_ContentPlaceHolder1_Accordion1').style.height = '100%';
} 

</script>

1
var EM = new events_managment();

EM.addEvent(window, 'resize', function(win,doc, event_){
    console.log('resized');
    //EM.removeEvent(win,doc, event_);
});

function events_managment(){
    this.events = {};
    this.addEvent = function(node, event_, func){
        if(node.addEventListener){
            if(event_ in this.events){
                node.addEventListener(event_, function(){
                    func(node, event_);
                    this.events[event_](win_doc, event_);
                }, true);
            }else{
                node.addEventListener(event_, function(){
                    func(node, event_);
                }, true);
            }
            this.events[event_] = func;
        }else if(node.attachEvent){

            var ie_event = 'on' + event_;
            if(ie_event in this.events){
                node.attachEvent(ie_event, function(){
                    func(node, ie_event);
                    this.events[ie_event]();
                });
            }else{
                node.attachEvent(ie_event, function(){
                    func(node, ie_event);
                });
            }
            this.events[ie_event] = func;
        }
    }
    this.removeEvent = function(node, event_){
        if(node.removeEventListener){
            node.removeEventListener(event_, this.events[event_], true);
            this.events[event_] = null;
            delete this.events[event_];
        }else if(node.detachEvent){
            node.detachEvent(event_, this.events[event_]);
            this.events[event_] = null;
            delete this.events[event_];
        }
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.