--- title: Intersection Observer API slug: Web/API/Intersection_Observer_API tags: - Intersection Observer API - пересечение объектов translation_of: Web/API/Intersection_Observer_API --- <p>{{DefaultAPISidebar("Intersection Observer API")}}</p> <p class="summary">Intersection Observer API позволяет веб-приложениям асинхронно следить за изменением пересечения элемента с его родителем или областью видимости документа {{Glossary("viewport")}}.</p> <p>Исторически обнаружение видимости отдельного элемента или видимости двух элементов по отношению друг к другу было непростой задачей. Варианты решения этой задачи были ненадежными и замедляли работу браузера. К несчастью, по мере того как веб "взрослел", потребность в решении этой проблемы только росла по многим причинам, таким как:</p> <ul> <li>Отложенная загрузка изображений или другого контента по мере прокрутки страницы.</li> <li>Реализация веб-сайтов с "бесконечным скроллом", где контент подгружается по мере того как страница прокручивается вниз, и пользователю не нужно переключаться между страницами.</li> <li>Отчет о видимости рекламы с целью посчитать доходы от нее.</li> <li>Принятие решения, запускать ли какой-то процесс или анимацию в зависимости от того, увидит пользователь результат или нет.</li> </ul> <p>В прошлом реализация обнаружения пересечения элементов подразумевала использование обработчиков событий и циклов, вызывающих методы типа {{domxref("Element.getBoundingClientRect()")}}, чтобы собрать необходимую информацию о каждом затронутом элементе. Поскольку весь этот код работает в основном потоке, возникают проблемы с производительностью.</p> <p>Рассмотрим веб-страницу с бесконечным скроллом. На ней используется библиотека для управления периодически размещаемой по всей странице рекламой, повсюду анимированная графика, а также библиотека для отображения всплывающих окон. И все эти вещи используют свои собственные правила для обнаружения пересечений, и все они запущены в основном потоке. Автор сайта может даже не подозревать об этой проблеме, а также может не знать, как работают сторонние библиотеки изнутри. В то же время пользователь по ходу прокрутки страницы сталкивается с тем, что работа сайта замедляется постоянным срабатыванием обнаружения пересечения, что в итоге приводит к тому, что пользователь недоволен браузером, сайтом и своим компьютером.</p> <p>Intersection Observer API даёт возможность зарегистрировать callback-функцию, которая выполнится при пересечении наблюдаемым элементом границ другого элемента (или области видимости документа {{Glossary("viewport")}}), либо при изменении величины пересечения на определенное значение. Таким образом, больше нет необходимости вычислять пересечение элементов в основном потоке, и браузер может оптимизировать эти процессы на своё усмотрение.</p> <p>Observer API не позволит узнать точное число пикселей или определить конкретные пиксели в пересечении; однако, его использование покрывает наиболее частые сценарии вроде "Если элементы пересекаются на N%, сделай то-то".</p> <h2 id="Основные_понятия">Основные понятия</h2> <p>Intersection Observer API позволяет указать функцию, которая будет вызвана всякий раз для элемента (<strong>target</strong>) при пересечении его с областью видимости документа (по умолчанию) или заданным элементом (<strong>root</strong>).</p> <p>В основном, используется отслеживание пересечения элемента с областью видимости (необходимо указать <code>null</code> в качестве корневого элемента).</p> <p>Используете ли вы область видимости или другой элемент в качестве корневого, API работает одинаково, вызывая заданную вами функцию обратного вызова, всякий раз, когда видимость целевого элемента изменяет так, что она пересекает в нужной степени корневой элемент.</p> <p>Степень пересечения целевого и корневого элемента задается в диапазоне от 0.0 до 1.0, где 1.0 это полное пересечение целевого элемента границ корневого.</p> <h3 id="Пример_использования">Пример использования</h3> <p>Для начала с помощью конструктора нужно создать объект-наблюдатель, указать для него функцию для вызова и настройки отслеживания:</p> <pre class="brush: js">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);</pre> <p>Параметр threshold со значением 1.0 означает что функция будет вызвана при 100% пересечении объекта (за которым мы следим) с объектом root</p> <h3 id="Настройки">Настройки</h3> <dl> <dt>root</dt> <dd>Элемент который используется в качестве области просмотра для проверки видимости целевого элемента. Должен быть предком целевого элемента. По умолчанию используется область видимости браузера если не определён или имеет значение <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.498039);">null</span></font>.</dd> <dt>rootMargin </dt> <dd>Отступы вокруг root. Могут иметь значения как свойство css margin: "<code>10px 20px 30px 40px" (top, right, bottom, left).</code> Значения можно задавать в процентах. По умолчанию все параметры установлены в нули.</dd> <dt>threshold</dt> <dd>Число или массив чисел, указывающий, при каком проценте видимости целевого элемента должен сработать callback. Например, в этом случае callback функция будет вызываться при появлении в зоне видимости каждый 25% целевого элемента: [0, 0.25, 0.5, 0.75, 1]</dd> </dl> <h4 id="Целевой_элемент_который_будет_наблюдаться">Целевой элемент, который будет наблюдаться</h4> <p>После того, как вы создали наблюдателя, вам нужно дать ему целевой элемент для просмотра:</p> <pre class="brush: js">var target = document.querySelector('#listItem'); observer.observe(target); </pre> <p>Всякий раз, когда цель достигает порогового значения, указанного для <code>IntersectionObserver</code>, вызывается функция обратного вызова <code>callback</code>. Где <code>callback</code> получает список объектов {{domxref ("IntersectionObserverEntry")}} и наблюдателя:</p> <pre class="brush: js">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 }); }; </pre> <p>Обратите внимание, что функция обратного вызова запускается в главном потоке и должна выполняться как можно быстрее, поэтому если что-то отнимает много времени, то используйте {{domxref("Window.requestIdleCallback()")}}.</p> <p>Также обратите внимание, что если вы указали опцию <code>root</code>, целевой элемент должен быть потомком корневого элемента.</p> <h2 id="Интерфейсы">Интерфейсы</h2> <dl> <dt>{{domxref("IntersectionObserver")}}</dt> <dd>Основной интерфейс для API Intersection Observer. Предоставляет методы для создания и управления observer, который может наблюдать любое количество целевых элементов для одной и той же конфигурации пересечения. Каждый observer может асинхронно наблюдать изменения в пересечении между одним или несколькими целевыми элементами и общим элементом-предком или с их верхним уровнем {{domxref("Document")}}'s {{Glossary('viewport')}}. Предок или область просмотра упоминается как <strong>root</strong>.</dd> <dt>{{domxref("IntersectionObserverEntry")}}</dt> <dd>Описывает пересечение между целевым элементом и его корневым контейнером в определенный момент перехода. Объекты этого типа могут быть получены только двумя способами: в качестве входных данных для вашего обратного вызова IntersectionObserver или путем вызова {{domxref ("IntersectionObserver.takeRecords()")}}.</dd> </dl> <h2 id="Спецификации">Спецификации</h2> <table class="standard-table"> <thead> <tr> <th scope="col">Спецификация</th> <th scope="col">Статус</th> <th scope="col">Комментарий</th> </tr> </thead> <tbody> <tr> <td>{{SpecName('IntersectionObserver')}}</td> <td>{{Spec2('IntersectionObserver')}}</td> <td></td> </tr> </tbody> </table> <h2 id="Совместимость_с_браузерами">Совместимость с браузерами</h2> <div class="hidden">Таблица совместимости на этой странице генерируется из структурированных данных. Если вы хотите внести свой вклад в эти данные, просмотрите https://github.com/mdn/browser-compat-data и отправьте нам запрос на извлечение.</div> <p>{{Compat("api.IntersectionObserver")}}</p> <h2 id="Смотрите_также">Смотрите также</h2> <ul> <li><a href="https://github.com/w3c/IntersectionObserver">Intersection Observer polyfill</a></li> <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API/Timing_element_visibility">Timing element visibility with the Intersection Observer API</a></li> <li>{{domxref("IntersectionObserver")}} and {{domxref("IntersectionObserverEntry")}}</li> </ul>