Spec-Zone.ru › Web APIs

ResizeObserver

Базовая поддержка Широко распространена

Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна в браузерах с июля 2020 года.

  • Узнать больше
  • Показать полную совместимость
  • Отправить отзыв

Интерфейс ResizeObserver сообщает об изменениях размеров содержимого или области рамки Element или области, ограничивающей SVGElement.

Примечание: Область содержимого — это область, в которой можно разместить содержимое, то есть область рамки за вычетом отступов и ширины рамки. Область рамки включает в себя содержимое, отступы и рамку. Подробное объяснение см. в разделе Модель области.

Конструктор

ResizeObserver()

Создаёт и возвращает новый объект ResizeObserver.

Свойства экземпляра

Нет.

Методы экземпляра

ResizeObserver.disconnect()

Отменяет наблюдение за всеми наблюдаемыми целевыми Element элементами данного наблюдателя.

ResizeObserver.observe()

Начинает наблюдение за указанным Element.

ResizeObserver.unobserve()

Завершает наблюдение за указанным Element.

Примеры

В примере resize-observer-text.html (посмотреть исходный код) мы используем наблюдатель изменений размера для изменения font-size заголовка и абзаца при изменении значения ползунка, что приводит к изменению ширины содержащей <div> области. Это демонстрирует, как можно реагировать на изменения размера элемента, даже если они никак не связаны с отображением.

Мы также предоставили флажок для включения и выключения наблюдателя. Если он выключен, текст не будет изменяться в ответ на изменение ширины <div>.

Следующий код на JavaScript:

const h1Elem = document.querySelector("h1");
const pElem = document.querySelector("p");
const divElem = document.querySelector("body > div");
const slider = document.querySelector('input[type="range"]');
const checkbox = document.querySelector('input[type="checkbox"]');

divElem.style.width = "600px";

slider.addEventListener("input", () => {
  divElem.style.width = `${slider.value}px`;
});

const resizeObserver = new ResizeObserver((entries) => {
  for (const entry of entries) {
    if (entry.contentBoxSize) {
      const contentBoxSize = entry.contentBoxSize[0];
      h1Elem.style.fontSize = `${Math.max(
        1.5,
        contentBoxSize.inlineSize / 200,
      )}rem`;
      pElem.style.fontSize = `${Math.max(
        1,
        contentBoxSize.inlineSize / 600,
      )}rem`;
    } else {
      h1Elem.style.fontSize = `${Math.max(
        1.5,
        entry.contentRect.width / 200,
      )}rem`;
      pElem.style.fontSize = `${Math.max(1, entry.contentRect.width / 600)}rem`;
    }
  }

  console.log("Size changed");
});

resizeObserver.observe(divElem);

checkbox.addEventListener("change", () => {
  if (checkbox.checked) {
    resizeObserver.observe(divElem);
  } else {
    resizeObserver.unobserve(divElem);
  }
});

Ошибки наблюдения

Реализации, соответствующие спецификации, вызывают события изменения размера до отрисовки (то есть до отображения кадра пользователю). Если имело место событие изменения размера, стили и макет повторно оцениваются, что, в свою очередь, может вызвать дополнительные события изменения размера. Бесконечные циклы из циклических зависимостей устраняются путём обработки только элементов, расположенных глубже в DOM, во время каждой итерации. События изменения размера, которые не удовлетворяют этому условию, откладываются до следующей отрисовки, и на объекте Window генерируется событие об ошибке с определённой строкой сообщения:

Цикл ResizeObserver завершён с непроданными уведомлениями.

Обратите внимание, что это предотвращает зависание пользовательского агента, но не сам бесконечный цикл. Например, следующий код приведёт к неограниченному увеличению ширины divElem с указанным выше сообщением об ошибке в консоли, повторяющимся в каждом кадре:

const divElem = document.querySelector("body > div");

const resizeObserver = new ResizeObserver((entries) => {
  for (const entry of entries) {
    entry.target.style.width = entry.contentBoxSize[0].inlineSize + 10 + "px";
  }
});

resizeObserver.observe(divElem);

window.addEventListener("error", (e) => {
  console.error(e.message);
});

До тех пор, пока событие об ошибке не будет генерироваться бесконечно, наблюдатель изменения размера стабилизируется и даёт стабильную, скорее всего правильную, компоновку. Однако пользователи могут увидеть кратковременное нарушение компоновки, так как последовательность изменений, которая должна произойти в одном кадре, вместо этого происходит в нескольких кадрах.

Чтобы предотвратить эти ошибки, решение зависит от того, какой эффект вы хотите получить. Если вы действительно хотите бесконечный цикл, вам нужно отложить код изменения размера в вашем обратном вызове ResizeObserver до момента, когда браузер перерисует содержимое. Вы можете поместить его в обратный вызов requestAnimationFrame.

const divElem = document.querySelector("body > div");

const resizeObserver = new ResizeObserver((entries) => {
  requestAnimationFrame(() => {
    for (const entry of entries) {
      entry.target.style.width = entry.contentBoxSize[0].inlineSize + 10 + "px";
    }
  });
});

resizeObserver.observe(divElem);

window.addEventListener("error", (e) => {
  console.error(e.message);
});

Если вы не хотите бесконечного цикла, убедитесь, что ваш код изменения размера не вызывает обратный вызов наблюдателя изменения размера. Есть много способов сделать это, например, задать «ожидаемый размер» и не изменять размер, если размер уже соответствует этому значению.

const divElem = document.querySelector("body > div");
const expectedSizes = new WeakMap();

const resizeObserver = new ResizeObserver((entries) => {
  requestAnimationFrame(() => {
    for (const entry of entries) {
      const expectedSize = expectedSizes.get(entry.target);
      if (entry.contentBoxSize[0].inlineSize === expectedSize) {
        continue;
      }
      const newSize = entry.contentBoxSize[0].inlineSize + 10;
      entry.target.style.width = `${newSize}px`;
      expectedSizes.set(entry.target, newSize);
    }
  });
});

resizeObserver.observe(divElem);

window.addEventListener("error", (e) => {
  console.error(e.message);
});

Спецификации

Спецификация
Наблюдатель изменения размера
# resize-observer-interface

Совместимость с браузерами

Рабочий стол Мобильные устройства
Chrome Edge Firefox Opera Safari Chrome Android Firefox for Android Opera Android Safari на iOS Samsung Internet WebView Android
ResizeObserver 64 79 69 51 13.1 64 79 47 13.4 9.0 64
ResizeObserver 64 79 69 51 13.1 64 79 47 13.4 9.0 64
disconnect 64 79 69 51 13.1 64 79 47 13.4 9.0 64
observe 64 79 69 51 13.1 64 79 47 13.4 9.0 64
unobserve 64 79 69 51 13.1 64 79 47 13.4 9.0 64

См. также

  • Урок: Модель области
  • PerformanceObserver
  • IntersectionObserver (часть API наблюдателей пересечения)
  • Скоро появятся запросы к контейнерам, которые могут стать подходящей альтернативой для реализации адаптивного дизайна.

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API