Intersection Observer API

Intersection Observer API позволяет веб-приложениям асинхронно следить за изменением пересечения элемента с его родителем или областью видимости документа viewport.

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

  • Отложенная загрузка изображений или другого контента по мере прокрутки страницы.
  • Реализация веб-сайтов с "бесконечным скроллом", где контент подгружается по мере того как страница прокручивается вниз, и пользователю не нужно переключаться между страницами.
  • Отчёт о видимости рекламы с целью посчитать доходы от неё.
  • Принятие решения, запускать ли какой-то процесс или анимацию в зависимости от того, увидит пользователь результат или нет.

В прошлом реализация обнаружения пересечения элементов подразумевала использование обработчиков событий и циклов, вызывающих методы типа Element.getBoundingClientRect(), чтобы собрать необходимую информацию о каждом затронутом элементе. Поскольку весь этот код работает в основном потоке, возникают проблемы с производительностью.

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

Intersection Observer API даёт возможность зарегистрировать колбэк-функцию, которая выполнится при пересечении наблюдаемым элементом границ другого элемента (или области видимости документа viewport), либо при изменении величины пересечения на определённое значение. Таким образом, больше нет необходимости вычислять пересечение элементов в основном потоке, и браузер может оптимизировать эти процессы на своё усмотрение.

Observer API не позволит узнать точное число пикселей или определить конкретные пиксели в пересечении; однако, его использование покрывает наиболее частые сценарии вроде "Если элементы пересекаются на N%, сделай то-то".

Основные понятия

Intersection Observer API позволяет указать функцию, которая будет вызвана всякий раз для элемента (target) при пересечении его с областью видимости документа (по умолчанию) или заданным элементом (root).

В основном, используется отслеживание пересечения элемента с областью видимости (необходимо указать null в качестве корневого элемента).

Используете ли вы область видимости или другой элемент в качестве корневого, API работает одинаково, вызывая заданную вами колбэк-функцию, всякий раз, когда видимость целевого элемента изменяет так, что она пересекает в нужной степени корневой элемент.

Степень пересечения целевого и корневого элемента задаётся в диапазоне от  0.0 до 1.0, где 1.0 это полное пересечение целевого элемента границ корневого.

Пример использования

Для начала с помощью конструктора нужно создать объект-наблюдатель, указать для него функцию для вызова и настройки отслеживания:

var options = {
    root: document.querySelector('#scrollArea'),
    rootMargin: '0px',
    threshold: 1.0
}
var callback = function(entries, observer) {
    /* Content excerpted, show below */
};
var observer = new IntersectionObserver(callback, options);

Параметр threshold со значением 1.0 означает что функция будет вызвана при 100% пересечении объекта (за которым мы следим) с объектом root

Настройки

root
Элемент который используется в качестве области просмотра для проверки видимости целевого элемента. Должен быть предком целевого элемента. По умолчанию используется область видимости браузера если не определён или имеет значение null.
rootMargin  
Отступы вокруг root.  Могут иметь значения как свойство css margin: "10px 20px 30px 40px" (top, right, bottom, left). Значения можно задавать в процентах. По умолчанию все параметры установлены в нули.
threshold
Число или массив чисел, указывающий, при каком проценте видимости целевого элемента должен сработать callback. Например, в этом случае callback функция будет вызываться при появлении в зоне видимости каждый 25% целевого элемента:  [0, 0.25, 0.5, 0.75, 1]

Целевой элемент, который будет наблюдаться

После того, как вы создали наблюдателя, вам нужно дать ему целевой элемент для просмотра:

var target = document.querySelector('#listItem');
observer.observe(target);

Всякий раз, когда цель достигает порогового значения, указанного для IntersectionObserver, вызывается колбэк-функция callback. Где callback получает список объектов IntersectionObserverEntry (en-US) и наблюдателя:

var callback = function(entries, observer) {
    entries.forEach(entry => {
        entry.time;               // a DOMHightResTimeStamp indicating when the intersection occurred.
        entry.rootBounds;         // a DOMRectReadOnly for the intersection observer's root.
        entry.boundingClientRect; // a DOMRectReadOnly for the intersection observer's target.
        entry.intersectionRect;   // a DOMRectReadOnly for the visible portion of the intersection observer's target.
        entry.intersectionRatio;  // the number for the ratio of the intersectionRect to the boundingClientRect.
        entry.target;             // the Element whose intersection with the intersection root changed.
        entry.isIntersecting;     // intersecting: true or false
    });
};

Обратите внимание, что колбэк-функция запускается в главном потоке и должна выполняться как можно быстрее, поэтому если что-то отнимает много времени, то используйте Window.requestIdleCallback().

Также обратите внимание, что если вы указали опцию root, целевой элемент должен быть потомком корневого элемента.

Интерфейсы

IntersectionObserver
Основной интерфейс для API Intersection Observer. Предоставляет методы для создания и управления observer, который может наблюдать любое количество целевых элементов для одной и той же конфигурации пересечения. Каждый observer может асинхронно наблюдать изменения в пересечении между одним или несколькими целевыми элементами и общим элементом-предком или с их верхним уровнем Document's viewport. Предок или область просмотра упоминается как root.
IntersectionObserverEntry (en-US)
Описывает пересечение между целевым элементом и его корневым контейнером в определённый момент перехода. Объекты этого типа могут быть получены только двумя способами: в качестве входных данных для вашего колбэка IntersectionObserver или путём вызова IntersectionObserver.takeRecords() (en-US).

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

Спецификация Статус Комментарий
Intersection Observer Рабочий черновик

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

BCD tables only load in the browser

Смотрите также