頁面可見性改變事件
visibilitychange
詳解
Page Visibility API 標准概述
這是一個頁面可見性API,瀏覽器標簽頁被隱藏或顯示的時候會觸發 visibilitychange事件。
這是 HTML5 新提供的一個 api ,作用是記錄當前標簽頁在瀏覽器中的激活狀態。
所謂“激活狀態”指當前標簽是否正在被用戶瀏覽。
我們知道,平時在 PC 端瀏覽網頁的時候,使用的都是選項卡這種方式瀏覽網頁,使用這種方式瀏覽,任何給定網頁都有可能在后台,因此對用戶不可見。頁面可見性 API 提供了開發者可以觀察的事件,以便了解文檔何時可見或隱藏,以及查看頁面當前可見性狀態的功能。
頁面可見性 API 對於節省資源和提到性能特別有用,它使頁面在文檔不可見時避免執行不必要的任務。
當用戶最小化窗口或切換到另一個選項卡時,API會發送 visibilitychange 事件,讓開發者知道頁面狀態已更改。你可以檢測事件並執行某些操作或行為。例如,如果你的網絡應用正在播放視頻,則可以在用戶將標簽放入背景時暫停視頻,並在用戶返回標簽時恢復播放。 用戶不會在視頻中丟失位置,視頻的音軌不會干擾新前景選項卡中的音頻,並且用戶在此期間不會錯過任何視頻。這種體驗是用戶無感知的,並且對於用戶體驗是非常友好的。
規范的使用這個API可以減少對用戶寬帶的占用,減少服務器壓力,節省用戶內存,以及到達更好的播放效果。
使用場景
- 網站有圖片輪播效果,只有在用戶觀看輪播的時候,才會自動展示下一張幻燈片。
- 顯示信息儀表盤的應用程序不希望在頁面不可見時輪詢服務器進行更新。
- 頁面想要檢測是否正在渲染,以便可以准確的計算網頁瀏覽量(埋點使用場景)。
- 當設備進入待機模式時,網站想要關閉設備聲音(用戶按下電源鍵關閉屏幕)。
該API的屬性和事件
HTML5 中專門為 document 元素添加了相關屬性和事件:
屬性
-
Document.hidden只讀屬性 布爾值 簡單的表示標簽頁顯示或者隱藏
如果頁面處於被認為是對用戶隱藏狀態時返回true,否則返回false。
-
Document.visibilityState只讀屬性
是一個用來展示文檔可見性狀態的字符串,可能的值:
visible: 頁面內容至少是部分可見。 在實際中,這意味着頁面是非最小化窗口的前景選項卡。hidden: 頁面內容對用戶不可見。 在實際中,這意味着文檔可以是一個后台標簽,或是最小化窗口的一部分,或是在操作系統鎖屏激活的狀態下。prerender: 頁面內容正在被預渲染且對用戶是不可見的(被document.hidden當做隱藏). 文檔可能初始狀態為prerender,但絕不會從其它值轉為該值。 注釋:瀏覽器支持是可選的。unloaded: 頁面正在從內存中卸載。 注釋:瀏覽器支持是可選的。
-
Document.onvisibilitychange
EventListener提供在visibilitychange事件被觸發時要調用的代碼。
基本應用
監聽該頁面可視狀態
function onVisibilityChange() {
if (!document[this.hiddenProperty]) {
console.log('頁面顯示');
} else {
console.log('頁面隱藏');
}
}
function addVisibilityListener() {
var hiddenProperty = 'hidden' in document ? 'hidden' : 'webkitHidden' in document ? 'webkitHidden' : 'mozHidden' in document ? 'mozHidden' : null;
var visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange');
document.addEventListener(visibilityChangeEvent, onVisibilityChange, false);
}
function removeVisilityListener() {
var hiddenProperty = 'hidden' in document ? 'hidden' : 'webkitHidden' in document ? 'webkitHidden' : 'mozHidden' in document ? 'mozHidden' : null;
var visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange');
document.removeEventListener(visibilityChangeEvent, onVisibilityChange, false);
}
控制視頻暫停⏸播放▶示例
// 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);
}
應用實例場景:帶有聲音的視頻
在此例中,當你切換到另一個標簽時視頻會暫停,當你返回到當前標簽時視頻會再次播放,代碼如下:
<main>
<video id="videoElement" controls="" poster="thumbnail.jpg">
<source src="https://s3-ap-northeast-1.amazonaws.com/daniemon/demos/The%2BVillage-Mobile.mp4" type="video/mp4" media="all and (max-width:680px)">
<source src="https://s3-ap-northeast-1.amazonaws.com/daniemon/demos/The%2BVillage-Mobile.webm" type="video/webm" media="all and (max-width:680px)">
<source src="https://s3-ap-northeast-1.amazonaws.com/daniemon/demos/The%2BVillage-SD.mp4" type="video/mp4">
<source src="https://s3-ap-northeast-1.amazonaws.com/daniemon/demos/The%2BVillage-SD.webm" type="video/webm">
<p>Sorry, there's a problem playing this video. Please try using a different browser.</p>
</video>
</main>
// 設置隱藏屬性和改變可見屬性的事件的名稱
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");
// 如果頁面是隱藏狀態,則暫停視頻;如果頁面是展示狀態,則播放視頻
function handleVisibilityChange() {
if (document[hidden]) {
videoElement.pause();
} else {
videoElement.play();
}
}
// 如果瀏覽器不支持addEventListener 或 Page Visibility API 給出警告
if (typeof document.addEventListener === "undefined" || typeof document[hidden] === "undefined") {
console.log("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
} else {
// 處理頁面可見屬性的改變
document.addEventListener(visibilityChange, handleVisibilityChange, false);
// 當視頻暫停,設置title
// This shows the paused
videoElement.addEventListener("pause", function(){
document.title = 'Paused';
}, false);
// 當視頻播放,設置title
videoElement.addEventListener("play", function(){
document.title = 'Playing';
}, false);
}
兼容性處理
為了支持老版本的瀏覽器,我們需要對document.hidden在做一些前綴處理:
function getHiddenProp(){
var prefixes = ['webkit','moz','ms','o'];
// 如果hidden 屬性是原生支持的,我們就直接返回
if ('hidden' in document) {
return 'hidden';
}
// 其他的情況就循環現有的瀏覽器前綴,拼接我們所需要的屬性
for (var i = 0; i < prefixes.length; i++){
// 如果當前的拼接的前綴在 document對象中存在 返回即可
if ((prefixes[i] + 'Hidden') in document) {
return prefixes[i] + 'Hidden';
}
}
// 其他的情況 直接返回null
return null;
}
同樣的,我們可以獲取 document.visibilityState 屬性:
function getVisibilityState() {
var prefixes = ['webkit', 'moz', 'ms', 'o'];
if ('visibilityState' in document) {
return 'visibilityState';
}
for (var i = 0; i < prefixes.length; i++) {
if ((prefixes[i] + 'VisibilityState') in document){
return prefixes[i] + 'VisibilityState';
}
}
// 找不到返回 null
return null;
}
visibilitychange監聽事件
你可以在 document 對象上注冊一個監聽 visibilitychange 事件,根據 document.hidden 或者 document.visibilityState 屬性做一些業務邏輯:
var visProp = getHiddenProp();
if (visProp) {
// 有些瀏覽器也需要對這個事件加前綴以便識別。
var evtname = visProp.replace(/[H|h]idden/, '') + 'visibilitychange';
document.addEventListener(evtname, function () {
document.title = document[getVisibilityState()]+"狀態";
},false);
}
上面的代碼會在頁面可見性發生變化時修改 document.title 的值
文章地址:https://www.cnblogs.com/dragonir/p/14417106.html 作者:dragonir
