Evento de redimensionamento da janela JavaScript

Como posso me conectar a um evento de redimensionamento da janela do navegador?

Há uma maneira jQuery de ouvir events de redimensionamento, mas eu preferiria não trazê-lo para o meu projeto apenas para este requisito.

O jQuery está apenas envolvendo o evento DOM de resize padrão, por exemplo.

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

O jQuery pode fazer algum trabalho para garantir que o evento de redimensionamento seja triggersdo consistentemente em todos os navegadores, mas não tenho certeza se algum dos navegadores é diferente, mas sugiro que você teste no Firefox, Safari e IE.

Nunca substitua a function window.onresize.

Em vez disso, crie uma function para adicionar um Event Listener ao object ou elemento. Isto verifica e coloca os ouvintes não funcionando, então ele sobrescreve a function do object como último recurso. Este é o método preferido usado em bibliotecas como o jQuery.

object : o elemento ou object de janela
type : resize, rolar (tipo de evento)
callback : a referência de function

 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; } }; 

Então use é assim:

 addEvent(window, "resize", function_reference); 

ou com uma function anônima:

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

Primeiramente, eu sei que o método addEventListener foi mencionado nos comentários acima, mas não vi nenhum código. Como é a abordagem preferida, aqui está:

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

Aqui está uma amostra de trabalho .

Acredito que a resposta correta já tenha sido fornecida pelo @Alex V, mas a resposta requer alguma modernização, já que tem mais de cinco anos agora.

Existem dois problemas principais:

  1. Nunca use o object como um nome de parâmetro. É uma palavra reservada. Com isso dito, a function fornecida pelo @Alex V não funcionará no strict mode .

  2. A function addEvent fornecida pelo @Alex V não retorna o event object se o método addEventListener for usado. Outro parâmetro deve ser adicionado à function addEvent para permitir isso.

OBSERVAÇÃO: O novo parâmetro para addEvent foi tornado opcional para que a migration para essa nova versão de function não interrompa nenhuma chamada anterior para essa function. Todos os usos herdados serão suportados.

Aqui está a function addEvent atualizada com estas mudanças:

 /* 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; }; 

Um exemplo de chamada para a nova function addEvent :

 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); 

O evento de redimensionamento nunca deve ser usado diretamente, pois é triggersdo continuamente à medida que redimensionamos.

Use uma function debounce para atenuar as chamadas em excesso.

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

Aqui está um debounce comum que flutua pela rede, embora procure por itens mais avançados como em lodash.

 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); }; }; 

Isso pode ser usado assim …

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

Ele nunca irá triggersr mais de uma vez a cada 200ms.

Para alterações de orientação móvel, use:

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

Aqui está uma pequena biblioteca que eu coloquei para cuidar disso perfeitamente.

Obrigado por referenciar minha postagem no blog em http://mbccs.blogspot.com/2007/11/fixing-window-resize-event-in-ie.html .

Enquanto você pode apenas conectar-se ao evento de redimensionamento de janela padrão, você descobrirá que no IE o evento é acionado uma vez para cada X e uma vez para cada movimento do eixo Y, resultando em uma tonelada de events sendo triggersdos que podem ter um desempenho impacto em seu site se a renderização for uma tarefa intensa.

Meu método envolve um tempo de espera curto que é cancelado em events subseqüentes para que o evento não seja gerado até seu código até que o usuário conclua o redimensionamento da janela.

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

A postagem do blog a seguir pode ser útil para você: Corrigir o evento de redimensionamento de janela no IE

Ele fornece este código:

 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); } 

Solução para 2018+:

Você deve usar ResizeObserver . Será uma solução nativa do navegador que tem um desempenho muito melhor do que usar o evento de resize . Além disso, ele não apenas suporta o evento no document mas também em elements arbitrários.

 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); 

Atualmente, apenas o Chrome é compatível, mas outros navegadores provavelmente seguirão (em breve). Por enquanto você tem que usar um polyfill .

As soluções mencionadas acima funcionarão se tudo o que você deseja fazer é resize apenas a janela e a janela. No entanto, se você quiser que o redimensionamento seja propagado para elementos filho, será necessário propagar o evento sozinho. Aqui está um código de exemplo para fazer isso:

 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); }); 

Observe que um elemento filho pode chamar

  event.preventDefault(); 

no object de evento que é passado como o primeiro Arg do evento de redimensionamento. Por exemplo:

 var child1 = document.getElementById("child1"); child1.addEventListener("resize", function (event) { ... event.preventDefault(); }); 
  
 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_]; } } }