1. 程式人生 > WINDOWS開發 >妙趣橫生的HTML5 Page Visibility API

妙趣橫生的HTML5 Page Visibility API

技術分享圖片

起因

最近瀏覽36kr 的網頁的時候偶然發現一個有趣的情況:當瀏覽器Tab 處於非當前頁的時候,36kr 的標題欄會自動換成可愛的大白字元形象。Jeff 在第一次看到的時候就知道這種效果是通過HTML5 的Page Visibility API 實現的(不是吹牛)。

技術分享圖片

直到現在我還沒去檢視36kr 的原始碼看其是如何實現的(也不打算去一個個檢視它繁雜的js 檔案了),HTML5 的Page Visibility API 以前看過,看到36kr 實現了這個的時候一時興起,遂去檢視文件深入瞭解之。然後三兩下在自己的部落格上實現了類似的效果(你可以切換Tab 到背後看看):

技術分享圖片

深入解析Page Visibility API

自從騰訊面試二面後,深深意識到“不去刨根問底的工程師跟搬磚的沒啥區別”;雖然我一直認為好的技術文不應該過多複製API 文件的內容,但在這裡還是從自己的角度為沒接觸過這個Page Visibility API 的同志們解析下。

荒蕪年代一統天下的IE6 早已成為過去時(也許你還記得以前用IE6的時候每開啟一個頁面就彈出一個新的視窗,層層疊疊),現代瀏覽器在多Tab (標籤後窗口)的構建形式上基本達成了共識,通常而言我們都是開啟新標籤頁,在當前瀏覽器視窗中,每次都只有一個標籤頁處於啟用態(或者說高亮),其餘均為隱藏態。HTML5 的那幫搞標準的也適時提出了這個Page Visibility API

——以期更好地利用這個“時隱時現”的動作。

在這裡我們先稍微離題下,可能你知道,Chrome 瀏覽器較一般瀏覽器能更好穩定執行的原因在於其引入了沙盒機制,每個新建的標籤頁甚至是每個擴充套件都是獨立在一個沙盒執行的。但如此一來帶來的是系統資源的佔用(Chrome 因耗記憶體被詬病就是如此來源於此)。回到正文,瀏覽器中每個標籤頁無論是啟用態還是隱藏態,運作機制模式基本沒啥區別的,原來該計算的還是在計算,原來在放視訊的還是在放視訊,佔記憶體的還是在佔記憶體。

但引入了Page Visibility API ,開發者可以做一些事情,讓我們設想下面的場景並提供相應的demo:

場景一:視訊網站使用者在看視訊時候切換到另外一個標籤頁了,視訊自動暫停(

點選檢視Demo);

場景二:一些耗效能的頁面在標籤頁處於隱藏狀態時候自動停止相關運算,節省資源(點選檢視Demo,援引自alloyteam);

場景三:好玩的,比如類似36kr 或本站的效果(點選檢視Demo)。

場景N:桌面提醒Notification 開啟隱藏態免打擾模式、流式載入的新聞頁面在處於隱藏態時偷偷載入最新內容……

基本上,有了這個API,制約你的就是你的idea,你的想象力了。

Page Visibility API使用方法

Page Visibility API 有兩個相關的屬性:document.visibilityStatedocument.hidden

document.visibilityState有如下四個值:

hidden:當瀏覽器最小化、切換tab(the page is on a background tab)、電腦鎖屏時visibilityState值是hidden

visible:當瀏覽器頂級context(top level browsing context)的document至少顯示在一個螢幕(screen)當中時,返visible;當瀏覽器視窗沒有最小化,但是瀏覽器被其他應用遮擋時,visibilityState值也是visible

prerender:文件載入離屏(is loaded off-screen)或者不可見時返回prerender,瀏覽器可選擇性的支援這個屬性(not all browsers will necessarily support it)

unloaded:當文件(document)將要被unload時返回unloaded,瀏覽器可選擇性的支援這個屬性

document.hidden 是個布林值屬性,標籤頁處於隱藏態則為false,反之啟用態為true。

最核心的是通過繫結visibilitychange 事件來達到需求:

document.addEventListener(‘visibilitychange‘,function(event) {
  if (!document.hidden) {
    // The page is visible.
  } else {
  // The page is hidden.
  }
});

因為相容性的原因需要為相關函式新增不同的瀏覽器字首:

 // Get Browser-Specifc Prefixfunction getBrowserPrefix() {

      // Check for the unprefixed property.  if (‘hidden‘ in document) {
        return null;
      }
  // All the possible prefixes.  var browserPrefixes = [‘moz‘,‘ms‘,‘o‘,‘webkit‘];

  for (var i = 0; i < browserPrefixes.length; i++) {
    var prefix = browserPrefixes[i] + ‘Hidden‘;
    if (prefix in document) {
      return browserPrefixes[i];
    }  }
  // The API is not supported in browser.  return null;
}
// Get Browser Specific Hidden Propertyfunction hiddenProperty(prefix) {
  if (prefix) {
    return prefix + ‘Hidden‘;
  } else {
    return ‘hidden‘;
  }}
// Get Browser Specific Visibility Statefunction visibilityState(prefix) {
  if (prefix) {
    return prefix + ‘VisibilityState‘;
  } else {
    return ‘visibilityState‘;
  }}
// Get Browser Specific Eventfunction visibilityEvent(prefix) {
  if (prefix) {
    return prefix + ‘visibilitychange‘;
  } else {
    return ‘visibilitychange‘;
  }}

更多使用方法請檢視上面的Demo 中的原始碼。

部分參考來源:

https://developer.mozilla.org/en-US/docs/Web/Guide/User_experience/Usi...

http://www.alloyteam.com/2012/11/page-visibility-api/

http://code.tutsplus.com/articles/html5-page-visibility-api–cms-22021