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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
|
---
title: Видимость страницы API
slug: Web/API/Page_Visibility_API
tags:
- API
- DOM
- Документ
- Показать страницу
- Скрыть страницу
translation_of: Web/API/Page_Visibility_API
original_slug: Web/API/Видимость_страницы_API
---
<div>{{DefaultAPISidebar("Page Visibility API")}}</div>
<p>При переключении между вкладками, web страница переходит в фоновый режим и поэтому не видна пользователю. Page Visibility API предоставляет события, которые вы можете отслеживать, чтобы узнать, когда страница станет видимой или скрытой, а так же возможность наблюдать текущее состояние видимости страницы.</p>
<div class="note">
<p><strong>Notes:</strong> The Page Visibility API особенно полезно для сбережения ресурсов и улучшения производительности, позволяя странице остановить выполнение не нужных задач, когда она не видна.</p>
</div>
<p>Когда пользователь сворачивает окно или переключается на другую вкладку, API отправляет {{event("visibilitychange")}} событие обработчикам, что состояние страницы изменилось. Вы можете отследить это событие и выполнить какие-то действия. Например, если ваше app проигрывает видео, его можно поставить на паузу, когда пользователь переключил вкладку (страница ушла в фон), а затем возобновить видео, когда пользователь вернулся на вкладку. Пользователь не теряет место на котором остановил просмотр, звук от видео не конфликтует с аудио новой вкладки, пользователь комфортно просмотреть оба видео.</p>
<p>Состояния видимости для {{HTMLElement("iframe")}} такие же как и для родительской страницы. Скрытие <code><iframe></code> используя CSS стили (такие как {{cssxref("display", "display: none;")}}) не вызывают события видимости и не изменяют состояние документа, содержащегося во фрейме.</p>
<h3 id="Использование">Использование</h3>
<p>Давайте рассмотрим несколько способов использования Page Visibility API.</p>
<ul>
<li>На сайте есть слайдер изображений с автопрокруткой, которую можно поставить на паузу, когда пользователь перешел на другую вкладку</li>
<li>Приложение выводит информацию в реальном времени, которую можно не обновлять, пока страница не видна, тем самым уменьшить количество запросов на сервер</li>
<li>Странице нужно понять, когда она должна быть отрисована, так что можно вести точный подсчет количества просмотров</li>
<li>Сайту нужно выключить звук, когда устройство в режиме ожидания (пользователь нажал кнопку включения, чтобы погасить экран)</li>
</ul>
<p>Раньше у разработчиков были не удобные способы. Например, обработка {{event("blur")}} и {{event("focus")}} событий на объекте window - помогала узнать когда страница становилась не активной, но это не давало возможность понять когда страница действительно скрыта от пользователя. Page Visibility API решает эту проблему.</p>
<div class="note">
<p><strong>Note:</strong> Когда {{domxref("GlobalEventHandlers.onblur", "onblur")}} и {{domxref("GlobalEventHandlers.onfocus", "onfocus")}} уведомляют, что пользователь переключил окна, это не означает, что оно действительно скрыто. Страница действительно скрыта, когда пользователь переключил вкладки или свернул окно браузера с этой вкладкой.</p>
</div>
<h3 id="Policies_in_place_to_aid_background_page_performance">Policies in place to aid background page performance</h3>
<p>Separately from the Page Visibility API, user agents typically have a number of policies in place to mitigate the performance impact of background or hidden tabs. These may include:</p>
<ul>
<li>Most browsers stop sending {{domxref("Window.requestAnimationFrame", "requestAnimationFrame()")}} callbacks to background tabs or hidden {{ HTMLElement("iframe") }}s in order to improve performance and battery life.</li>
<li>Timers such as {{domxref("WindowOrWorkerGlobalScope.setTimeout", "setTimeout()")}} are throttled in background/inactive tabs to help improve performance. See <a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#Reasons_for_delays_longer_than_specified">Reasons for delays longer than specified</a> for more details.</li>
<li>Budget-based background timeout throttling is now available in modern browsers (Firefox 58+, Chrome 57+), placing an additional limit on background timer CPU usage. This operates in a similar way across modern browsers, with the details being as follows:
<ul>
<li>In Firefox, windows in background tabs each have their own time budget in milliseconds — a max and a min value of +50 ms and -150 ms, respectively. Chrome is very similar except that the budget is specified in seconds.</li>
<li>Windows are subjected to throttling after 30 seconds, with the same throttling delay rules as specified for window timers (again, see <a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#Reasons_for_delays_longer_than_specified">Reasons for delays longer than specified</a>). In Chrome, this value is 10 seconds.</li>
<li>Timer tasks are only permitted when the budget is non-negative.</li>
<li>Once a timer's code has finished running, the duration of time it took to execute is subtracted from its window's timeout budget.</li>
<li>The budget regenerates at a rate of 10 ms per second, in both Firefox and Chrome.</li>
</ul>
</li>
</ul>
<p>Some processes are exempt from this throttling behavior. In these cases, you can use the Page Visibility API to reduce the tabs' performance impact while they're hidden.</p>
<ul>
<li>Tabs which are playing audio are considered foreground and aren’t throttled.</li>
<li>Tabs running code that's using real-time network connections (<a href="/en-US/docs/Web/API/WebSockets_API">WebSockets</a> and <a href="/en-US/docs/Web/API/WebRTC_API">WebRTC</a>) go unthrottled in order to avoid closing these connections timing out and getting unexpectedly closed.</li>
<li><a href="/en-US/docs/Web/API/IndexedDB_API">IndexedDB</a> processes are also left unthrottled in order to avoid timeouts.</li>
</ul>
<h2 id="Example">Example</h2>
<p>View <a href="http://daniemon.com/tech/webapps/page-visibility/">live example</a> (video with sound).</p>
<p>The example, which pauses the video when you switch to another tab and plays again when you return to its tab, was created with the following code:</p>
<pre class="brush: js notranslate">// Set the name of the hidden property and the change event for visibility
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
}
var videoElement = document.getElementById("videoElement");
// If the page is hidden, pause the video;
// if the page is shown, play the video
function handleVisibilityChange() {
if (document[hidden]) {
videoElement.pause();
} else {
videoElement.play();
}
}
// Warn if the browser doesn't support addEventListener or the Page Visibility API
if (typeof document.addEventListener === "undefined" || hidden === undefined) {
console.log("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
} else {
// Handle page visibility change
document.addEventListener(visibilityChange, handleVisibilityChange, false);
// When the video pauses, set the title.
// This shows the paused
videoElement.addEventListener("pause", function(){
document.title = 'Paused';
}, false);
// When the video plays, set the title.
videoElement.addEventListener("play", function(){
document.title = 'Playing';
}, false);
}
</pre>
<h2 id="Properties_added_to_the_Document_interface">Properties added to the Document interface</h2>
<p>The Page Visibility API adds the following properties to the {{domxref("Document")}} interface:</p>
<dl>
<dt>{{domxref("Document.hidden")}} {{ReadOnlyInline}}</dt>
<dd>Returns <code>true</code> if the page is in a state considered to be hidden to the user, and <code>false</code> otherwise.</dd>
<dt>{{domxref("Document.visibilityState")}} {{ReadOnlyInline}}</dt>
<dd>A {{domxref("DOMString")}} indicating the document's current visibility state. Possible values are:
<dl>
<dt><code>visible</code></dt>
<dd>The page content may be at least partially visible. In practice this means that the page is the foreground tab of a non-minimized window.</dd>
<dt><code>hidden</code></dt>
<dd>The page's content is not visible to the user, either due to the document's tab being in the background or part of a window that is minimized, or because the device's screen is off.</dd>
<dt><code>prerender</code></dt>
<dd>The page's content is being prerendered and is not visible to the user. A document may start in the <code>prerender</code> state, but will never switch to this state from any other state, since a document can only prerender once.
<div class="note"><strong>Note:</strong> Not all browsers support prerendering.</div>
</dd>
<dt><code>unloaded</code></dt>
<dd>The page is in the process of being unloaded from memory.
<div class="note"><strong>Note:</strong> Not all browsers support the <code>unloaded</code> value.</div>
</dd>
</dl>
</dd>
<dt>{{domxref("Document.onvisibilitychange")}}</dt>
<dd>An {{domxref("EventListener")}} providing the code to be called when the {{event("visibilitychange")}} event is fired.</dd>
</dl>
<pre class="brush: js notranslate">//startSimulation and pauseSimulation defined elsewhere
function handleVisibilityChange() {
if (document.hidden) {
pauseSimulation();
} else {
startSimulation();
}
}
document.addEventListener("visibilitychange", handleVisibilityChange, false);
</pre>
<h2 id="Specifications">Specifications</h2>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Specification</th>
<th scope="col">Status</th>
<th scope="col">Comment</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{SpecName('Page Visibility API')}}</td>
<td>{{Spec2('Page Visibility API')}}</td>
<td>Initial definition.</td>
</tr>
</tbody>
</table>
<h2 id="Browser_compatibility">Browser compatibility</h2>
<div>
<h3 id="Document.visibilityState"><code>Document.visibilityState</code></h3>
<div>
<p>{{Compat("api.Document.visibilityState")}}</p>
</div>
</div>
<h2 id="See_also">See also</h2>
<ul>
<li>Description of the <a href="http://blogs.msdn.com/b/ie/archive/2011/07/08/using-pc-hardware-more-efficiently-in-html5-new-web-performance-apis-part-2.aspx" title="Page Visibility on IEBlog">Page Visibility API</a> on the IEBlog.</li>
<li>Description of the <a href="http://code.google.com/chrome/whitepapers/pagevisibility.html" title="Page Visibility API by Google">Page Visibility API</a> by Google</li>
</ul>
|