1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
---
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 даёт возможность зарегистрировать колбэк-функцию, которая выполнится при пересечении наблюдаемым элементом границ другого элемента (или области видимости документа {{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>
{{Specifications}}
<h2 id="Совместимость_с_браузерами">Совместимость с браузерами</h2>
<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>
|