Событие изменения размера окна JavaScript

Как я могу подключиться к событию изменения размера окна браузера?

Существует способ прослушивания событий изменения размера в jQuery, но я бы предпочел не включать его в свой проект только по одному этому требованию.

12 ответов

Решение

JQuery это просто стандарт resize Событие DOM, например.

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

jQuery может сделать некоторую работу, чтобы гарантировать, что событие resize будет срабатывать согласованно во всех браузерах, но я не уверен, что какой-либо из браузеров отличается, но я бы посоветовал вам протестировать в Firefox, Safari и IE.

Во-первых, я знаю addEventListener Метод был упомянут в комментариях выше, но я не видел никакого кода. Поскольку это предпочтительный подход, вот он:

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

Вот рабочий образец.

Никогда не отменяйте функцию window.onresize.

Вместо этого создайте функцию для добавления прослушивателя событий к объекту или элементу. Это проверяет, что слушатели не работают, а затем переопределяет функцию объекта как последнее средство. Это предпочтительный метод, используемый в библиотеках, таких как jQuery.

object: элемент или оконный объект
type: изменить размер, прокрутить (тип события)
callback: ссылка на функцию

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

Тогда используйте это так:

addEvent(window, "resize", function_reference);

или с анонимной функцией:

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

Решение для 2018+:

Вы должны использовать ResizeObserver. Это будет нативное для браузера решение, которое имеет гораздо лучшую производительность, чем использование resize событие. Кроме того, он не только поддерживает событие на document но и на произвольном 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);

В настоящее время только Chrome поддерживает его, но другие браузеры, вероятно, последуют (скоро). На данный момент вы должны использовать полифилл.

Событие resize никогда не должно использоваться напрямую, так как оно запускается непрерывно при изменении размера.

Используйте функцию debounce, чтобы уменьшить лишние вызовы.

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

Вот распространенный дебат, распространяющийся по сети, хотя более продвинутые ищите, как featuerd в 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);
    };
};

Это можно использовать как так...

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

Он никогда не будет срабатывать чаще, чем раз в 200 мс.

Для изменений мобильной ориентации используйте:

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

Вот небольшая библиотека, которую я собрал, чтобы аккуратно позаботиться об этом.

Я верю, что @Alex V уже предоставил правильный ответ, но ответ требует некоторой модернизации, так как ему уже более пяти лет.

Есть два основных вопроса:

  1. Никогда не используйте object в качестве имени параметра. Это зарезервированное слово. Учитывая сказанное, предоставляемая функция @Alex V не будет работать в strict mode,

  2. addEvent Функция, предоставляемая @Alex V, не возвращает event object если addEventListener метод используется. Другой параметр должен быть добавлен к addEvent функция, чтобы учесть это.

ПРИМЕЧАНИЕ. Новый параметр addEvent был сделан необязательным, чтобы переход на эту новую версию функции не нарушал предыдущие вызовы этой функции. Все устаревшие варианты использования будут поддерживаться.

Вот обновленный addEvent работать с этими изменениями:

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

Пример вызова к новому 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);

Спасибо за ссылку на мой пост в блоге на http://mbccs.blogspot.com/2007/11/fixing-window-resize-event-in-ie.html.

Хотя вы можете просто подключиться к стандартному событию изменения размера окна, вы обнаружите, что в IE событие запускается один раз для каждого X и один раз для каждого движения оси Y, в результате чего запускается тонна событий, которые могут иметь производительность влияние на ваш сайт, если рендеринг является интенсивной задачей.

Мой метод предусматривает короткий тайм-аут, который отменяется при последующих событиях, чтобы событие не попадало в ваш код, пока пользователь не завершил изменение размера окна.

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

Следующее сообщение в блоге может быть полезно для вас: Исправление события изменения размера окна в IE

Он предоставляет этот код:

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

Уже упомянутые выше решения будут работать, если все, что вы хотите сделать, это изменить размер окна и только окна. Однако, если вы хотите, чтобы изменение размера распространялось на дочерние элементы, вам нужно будет распространить событие самостоятельно. Вот пример кода, чтобы сделать это:

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

Обратите внимание, что дочерний элемент может вызывать

 event.preventDefault();

на объекте события, который передается в качестве первого Arg события resize. Например:

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

Вы можете использовать следующий подход, который подходит для небольших проектов.

       <body onresize="yourHandler(event)">

         function yourHandler(e) {
  console.log('Resized:', e.target.innerWidth)
}
         <body onresize="yourHandler(event)">
  Content... (resize browser to see)
</body>

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_];
        }
    }
}
<script language="javascript">
    window.onresize = function() {
    document.getElementById('ctl00_ContentPlaceHolder1_Accordion1').style.height = '100%';
} 

</script>
Другие вопросы по тегам