1、Page Visibility API標准概述
查看W3C的官方文檔時候看到這個屬性 標准時間線是這樣介紹的:
Page Visibility Level 2
W3C Proposed Recommendation 17 October 2017
查看W3C的工作流程的時候可以看到應該是處於W3C提議推薦的階段,雖然還沒有被完全的推薦成為標准,並且不是每一款瀏覽器都有所支持,但還是值得研究一下。
2、定義
顧名思義這是一個頁面可見性API。
簡單的說,瀏覽器標簽頁被隱藏或顯示的時候會觸發visibilitychange
事件。
這是HTML5新提供的一個api,作用是記錄當前標簽頁在瀏覽器中的激活狀態。
所謂“激活狀態”指當前標簽是否正在被用戶瀏覽。
我們知道,平時在PC端瀏覽網頁的時候,使用的都是選項卡這種方式瀏覽網頁,使用這種方式瀏覽,任何給定網頁都有可能在后台,因此對用戶不可見。頁面可見性API提供了開發者可以觀察的事件,以便了解文檔何時可見或隱藏,以及查看頁面當前可見性狀態的功能。
頁面可見性API對於節省資源和提到性能特別有用,它使頁面在文檔不可見時避免執行不必要的任務。
當用戶最小化窗口或切換到另一個選項卡時,API會發送visibilitychange事件,讓開發者知道頁面狀態已更改。你可以檢測事件並執行某些操作或行為。例如,如果你的網絡應用正在播放視頻,則可以在用戶將標簽放入背景時暫停視頻,並在用戶返回標簽時恢復播放。 用戶不會在視頻中丟失位置,視頻的音軌不會干擾新前景選項卡中的音頻,並且用戶在此期間不會錯過任何視頻。這種體驗是用戶無感知的,並且對於用戶體驗是非常友好的。
因此規范的使用這個API可以減少對用戶寬帶的占用,減少服務器壓力,節省用戶內存,以及到達更好的播放效果。
3.羅列一些使用場景
1.網站有圖片輪播效果,只有在用戶觀看輪播的時候,才會自動展示下一張幻燈片。
2.顯示信息儀表盤的應用程序不希望在頁面不可見時輪詢服務器進行更新。
3.頁面想要檢測是否正在渲染,以便可以准確的計算網頁瀏覽量(埋點使用場景)。
4.當設備進入待機模式時,網站想要關閉設備聲音(用戶按下電源鍵關閉屏幕)。
4. 該API的屬性和事件
HTML5中專門為document
元素添加了相關屬性和事件:
屬性:
1、
Document.hidden
只讀屬性 布爾值 簡單的表示標簽頁顯示或者隱藏
如果頁面處於被認為是對用戶隱藏狀態時返回true,否則返回false。
2、Document.visibilityState
只讀屬性
是一個用來展示文檔可見性狀態的字符串,可能的值:
visible
: 頁面內容至少是部分可見。 在實際中,這意味着頁面是非最小化窗口的前景選項卡。
hidden
: 頁面內容對用戶不可見。 在實際中,這意味着文檔可以是一個后台標簽,或是最小化窗口的一部分,或是在操作系統鎖屏激活的狀態下。
prerender
: 頁面內容正在被預渲染且對用戶是不可見的(被document.hidden
當做隱藏). 文檔可能初始狀態為prerender
,但絕不會從其它值轉為該值。 注釋:瀏覽器支持是可選的。
unloaded
: 頁面正在從內存中卸載。 注釋:瀏覽器支持是可選的。
3、Document.onvisibilitychange
EventListener
提供在visibilitychange
事件被觸發時要調用的代碼。
5.應用實例場景:帶有聲音的視頻
在此例中,當你切換到另一個標簽時視頻會暫停,當你返回到當前標簽時視頻會再次播放,代碼如下:
<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); }
6兼容性處理
為了支持老版本的瀏覽器,我們需要對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的值