aboutsummaryrefslogtreecommitdiff
path: root/files/ru/web/api/intersection_observer_api/index.html
blob: bd086266e61221dfcd1b6efeae8d5a2287fb1f61 (plain)
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
---
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 =&gt; {
        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>