Что такое Intersection Observer API и как его использовать в JavaScript

Intersection Observer API: основные параметры и настройки

19.02.2021
112
6 мин.
0

Простота использования настроек Intersection Observer API (IOA) позволяет существенно упростить написание кода для слежения за элементами в зоне видимости и расширить возможности использования нативного JavaScript.

В предыдущей статье мы ознакомились с основами использования Intersection Observer API. Теперь давайте остановимся подробнее на некоторых его опциях для настройки «наблюдателя». Мы также рассмотрим два разных подхода для наблюдения сразу за несколькими элементами.

Опции и настройки Intersection Observer API

Интерфейс Intersection Observer API предоставляет возможность применять несколько опций и настроек. Например, имеется возможность передачи массива параметров (все они необязательны) в качестве второго аргумента конструктора new IntersectionObserver():

  • root — родительский элемент для наблюдения за целевыми элементами, расположенными внутри него. По умолчанию — это область просмотра, но им также может быть и любой другой прокручиваемый элемент.
  • rootMargin — маргины, используемые для корневого элемента при обнаружении пересечения. Этот параметр работает аналогично свойству margin в CSS, и по умолчанию имеет значение 0px 0px 0px 0px. Установка положительного числа приведет к тому, что наблюдаемые элементы будут иметь значение isIntersecting, равное true, прежде чем они появятся в области видимости (или другом родительском элементе — root).
  • threshold — параметр Intersection Observer API, отвечающий за то, какая часть элемента должна находиться в области видимости (или в root элементе), чтобы он считаться видимым. Значение 0 (установлено по умолчанию) означает, что учитывается даже один пиксель, значение 1 — что все пиксели элемента должны быть видны. Для срабатывания метода при появлении элемента на 25% достаточно установить пороговое значение в 0,25. Можно передать одно число или массив чисел.

Например, представим, что нам нужно отложить загрузку текста в определенные блоки, когда они находятся на расстоянии 50 пикселей от границы входа в область видимости.

Для удобства чтения давайте также перенесем функцию обратного вызова в ее собственную именованную функцию.

// Ленивая загрузка текста 
function loadText (entries, obs) { 
    entries.forEach(function (entry) { 
// Если наблюдаемый элемент находится за пределами зоны видимости, то ничего не происходит 
        if (!entry.isIntersecting) return; 
// Отключаем «наблюдателя» 
        obs.unobserve(entry.target); 
// Выводим в консоль сообщение, когда элемент войдет в зону видимости 
        console.log('Элемент в зоне видимости'); 
// Добавляем в него текст 
        entry.target.textContent += 'Элемент в зоне видимости'; 
    }); 
} 

// Задаем опции для «наблюдателя»
 let options = { 
    rootMargin: '50px' 
}; 

// Создаем новый «наблюдатель» 
let observer = new IntersectionObserver(loadText, options); // Указываем элемент для «наблюдения» 
let app = document.querySelector('.element'); 
// Прикрепляем «наблюдателя» к элементу observer.observe(app);

Наблюдение за несколькими элементами

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

При наблюдении за несколькими элементами сразу массив entries может (но не обязательно) содержать несколько элементов.

Если element_1 и element_2 не расположены рядом друг с другом, один может покинуть область просмотра, когда второй еще в нее не вошел. В этой ситуации тот, который из нее выйдет, сохраняется в массиве entries со значением isIntersecting равным false. А второй будет иметь значение true.

// Создаем новый «наблюдатель» 
let observer = new IntersectionObserver( function (entries) { 
    console.log(entries); 
    entries.forEach(function (entry) { 
        console.log(entry.target); 
        console.log(entry.isIntersecting);
     }); 
}); 

// Указываем элементы для «наблюдения» 
let el_1 = document.querySelector('.element_1'); 
let el_2 = document.querySelector('.element_2'); 

// Прикрепляем элементы к «наблюдателя» observer.observe(el_1); 
observer.observe(el_2);

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

Что такое Intersection Observer API и как его использовать в JavaScript
Базовые настройки и параметры Intersection Observer API в JavaScript (изображение создано с помощью ИИ)

Альтернативный шаблон — один наблюдатель на элемент

Подключение нескольких элементов к одному Intersection Observer API может привести к некоторым неудобствам. Это в первую очередь актуально при командной работе над одним проектом.

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

Еще одним способом является создание вспомогательной функции, которая создает новый конструктор IntersectionObserver(). Она активирует «наблюдение» за элементом и вернет «наблюдателя» (observer).

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

Читайте также: Как использовать буфер обмена через navigator.clipboard API.

/**
Создаем intersection observer
elem - элемент для «наблюдения»
callback - callback-функция
options - объект опций, если они необходимы (необязательный параметр)
*/
function createIntersectionObserver (elem, callback, options) {
    let observer = new IntersectionObserver(callback, options || {});
    observer.observe(elem);
    return observer;
}

/**
Выводим в консоль элемент, если он входит в зону видимости
entries - массив «наблюдаемых» элементов
 */
function log (entries) {
    let [entry] = entries;
    console.log(entries);
    console.log(entry.target);
    console.log(entry.isIntersecting);
}

// Задаем опции для «наблюдателя»
let options = {
    rootMargin: '50px'
};

// Указываем элементы для «наблюдения»
let el_1 = document.querySelector('.element_1');
let el_2 = document.querySelector('.element_2');

/**
Создаем «наблюдателя» для каждого элемента
Для первого указываем опции
*/
createIntersectionObserver(el_1, log, options);

// Второй использует ту же самую callback-функцию, но без опций
createIntersectionObserver(el_2, log);

В свое время этот способ применения Intersection Observer API вызвал многочисленные споры. Однако в результате большинство ведущих разработчиков пришли к следующему выводу.

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

Кроссбраузерность Intersection Observer API

Помимо Internet Explorer этот API браузера имеет полную поддержку.