Page Visibility(頁面可見性) API介紹、微拓展
旭哥推薦:3月31日前,點選註冊啟用 Coding.net 立贈30天付費會員。體驗極速程式碼託管服務!
一、網頁君的悲情誰來懂
唉,突然想到了一首悲情詩:
淚溼羅巾夢不成,夜深前殿按歌聲。
紅顏未老恩先斷, 斜倚薰籠坐到明。
學生時代學過的一首詩,已還給老師不知所云的諸位可參見下面釋義:
詩的主人公是一位不幸的宮女。她一心盼望君王的臨幸而終未盼得,時已深夜,只好上床,已是一層怨悵。寵幸不可得,退而求之好夢;輾轉反側,竟連夢也難成,見出兩層怨悵。夢既不成,索性攬衣推枕,掙扎坐起。正當她愁苦難忍,淚溼羅巾之時,前殿又傳來陣陣笙歌,原來君王正在那邊尋歡作樂,這就有了三層怨悵。倘使人老珠黃,猶可解說;偏偏她盛鬢堆鴉,紅顏未老,生出四層怨悵。要是君王一直沒有發現她,那也罷了;事實是她曾受過君王的恩寵,而現在這種恩寵卻無端斷絕,見出五層怨悵。夜已深沉,瀕於絕望,但一轉念,猶翼君王在聽歌賞舞之後,會記起她來。於是,斜倚熏籠,濃薰翠袖,以待召幸。不料,一直坐到天明,幻想終歸破滅,見出六層怨悵。
為何在這陽光和煦,安靜愜意的溫暖冬日會有如此感傷呢?
唉,只因自己想到了可憐的網頁君,其命運就跟深宮的宮女一般,令人唏噓。
某君王啪啪啪啪打開了十幾二十個選項卡(就像他當初啪啪啪啪寵幸後宮那十幾二十個宮女一樣);但是,鞭長莫及,其一次只能瀏覽一個選項卡(就像他每晚只能寵幸一個宮女一樣);可是,其他的選項卡並不知道君王何時會再過來(就像其他的宮女並不清楚君王今晚會不會來寵幸一樣);於是,其他選項卡依然在不停地執行,守候(就像宮女依然留有希望,等待召幸);然而,最後,君王直接啪一下瀏覽器關掉了,N多不停忠心守候的選項卡被無情漠視了(就像宮女們苦守整夜,結果卻是一場空,只能以淚洗面)!
此番悲情怎能不讓人同情憐憫,是不是啊,諸位!
哼,請不要擺出這樣或這樣的表情。
那個誰誰,說的就是你!你應該這樣子或這樣子。
您應該像扎西拉姆·多多一樣,為悲情網頁君賦詩一首——《見與不見》:
你見,或者不見我
我就在那裡
不悲不喜
你念,或者不念我
情就在那裡
不來不去……
時代在發展,制度也會進步。比方說明代吧,每日天漸黑時,嬪妃所住的宮門前,都掛起兩隻紅紗籠燈。皇帝臨幸某宮,則該宮門上的燈卸下來,表示皇帝已選定寢宿的地方。於是,負責巡街的宦官,傳令其他各宮均卸燈寢息。失意的嬪妃們只得滅掉希求寵幸的紅紗籠,明晚再重新掛上。
這就避免了嬪妃們徹夜苦等,哀怨淚雨的情形。
那網頁君這邊呢?
好在,就最近幾年,網頁君也有了相應的東西,可以告知網頁你是“寵幸”了呢還是不被“寵幸”,這樣,可以讓網頁君在不被“寵幸”時候安心睡覺,或者養個小白。這個東西就是Page Visibility API,翻譯成簡體中文就是“頁面可見性應用程式介面”。
於是乎,網頁君的悲情程度可以lower一點了,從這點來說,Page Visibility API是個很人性化的設計,感動!
//zxx: 為接地氣,下”Page Visibility API”均稱呼為“頁面可見性API”。
二、頁面可見性API究竟為何物?
CSS中有個有用且有趣且個人比較喜歡的屬性 – visibility
. 其有兩個常用屬性值:hidden
與visible
. 分別表示不可見與可見。OK,本文所說的API中也有Visibility
這個單詞,那他們表意一致?
回答是:YES! //眾人:妹啊,你以為是中國達人秀啊!
頁面可見性API就是表示網頁可見還是不可見的,巧的是,hidden
與visible
就是該API的兩個狀態值。
舉個通俗的例子:
如果你在xxxxx.com上瀏覽提神的圖片,則當前你所看的這個網頁的visibility
就是visible
.
此時,如果你老媽子突然進來給你送香蕉,出現下圖所示場景:
則,此時之前提神的網頁的visibility
就是hidden
– 最小化。
或者老媽子進來的時候,切換到人民網,提神網頁的visibility
也是hidden
– 切換選項卡。
老媽子送的香蕉~~啦啦啦啦啦~~
這就是頁面可見性API的直觀認識,至於其身上哪裡有麻子,下面會指出.
三、頁面可見性API屬性和事件
目前頁面可見性API有兩個屬性,一個事件,如下:
document.hidden
: Boolean值,表示當前頁面可見還是不可見document.visibilityState
: 返回當前頁面的可見狀態。- “
hidden
“ - “
visible
“ - “
prerender
” 這個表示納尼呢~~恩,我也不確定,字面意思是“預渲染”。莫非指的是啪啪啪一下子開了很多個選項卡,之前選項卡依然在載入渲染的狀態?或者說是瀏覽器新開啟時記住的上一次關閉選項卡的狀態?求達人指明! - “
preview
” 預覽。根據部分2011年底相關國外部分文章的說法,這種狀態出現在,如window7系統下,滑鼠放在底部(一般是)工作列的圖示上(預覽)的時候。見下截圖:
但是根據自己的實際測試,似乎並沒有這種狀態的改變——包括IE10瀏覽器。可能是時代改變,一切都遵循規範了吧。因此,我們重點關注前面三個狀態值就可以了。
- “
visibilitychange
: 當可見狀態改變時候觸發的事件。
四、瀏覽器支援與私有字首
我寫了個如下的頁面可見性API支援性的測試程式碼:
var isPageVisibilitySupport = (function() { var support = false; if (typeof window.screenX === "number") { ["webkit", "moz", "ms", "o", ""].forEach(function(prefix) { if (support == false && document[prefix + (prefix? "H": "h") + "idden"] + "" !== "undefined") { support = true; } }); } return support; })();
測試發現,如下瀏覽器都是支援的:
- Chrome 21
- FireFox 16.0.2
- Opera 12.11
- IE10
不支援的瀏覽器:
- IE9
- Safari 5.1
因此,typeof document.msHidden != "undefined"
可以用來區分IE9瀏覽器還是IE10瀏覽器。
正如上面的code所展示的,頁面可見性API的所有屬性以及事件,目前是需要使用私有字首的(如果沒有這些字首,瀏覽器就不認識這些屬性或方法了)。
一旦有了字首,實際應用的時候程式碼就有些囉哩吧嗦了(可見參見文章底部參考文章中展示的程式碼)!
因為要一個字首一個字首判斷——oh, my! 我這個懶人最不喜歡這等麻煩事了,於是,撈起袖子,啪啪啪啪整個一個相容性的Page Visibility API相關物件,正好包含API中的兩個屬性以及一個事件。完整程式碼如下(節省篇幅,滾動顯示。如果您發現沒有滾動效果啊?可能是由於在其他網站或是RSS中閱讀本文,本文原地址:http://www.zhangxinxu.com/wordpress/?p=2790,本文作者:張鑫旭,來自張鑫旭-鑫空間-鑫生活,訪問原出處閱讀體驗更佳。
):
var pageVisibility = (function() { var prefixSupport, keyWithPrefix = function(prefix, key) { if (prefix !== "") { // 首字母大寫 return prefix + key.slice(0,1).toUpperCase() + key.slice(1); } return key; }; var isPageVisibilitySupport = (function() { var support = false; if (typeof window.screenX === "number") { ["webkit", "moz", "ms", "o", ""].forEach(function(prefix) { if (support == false && document[keyWithPrefix(prefix, "hidden")] != undefined) { prefixSupport = prefix; support = true; } }); } return support; })(); var isHidden = function() { if (isPageVisibilitySupport) { return document[keyWithPrefix(prefixSupport, "hidden")]; } return undefined; }; var visibilityState = function() { if (isPageVisibilitySupport) { return document[keyWithPrefix(prefixSupport, "visibilityState")]; } return undefined; }; return { hidden: isHidden(), visibilityState: visibilityState(), visibilitychange: function(fn, usecapture) { usecapture = undefined || false; if (isPageVisibilitySupport && typeof fn === "function") { return document.addEventListener(prefixSupport + "visibilitychange", function(evt) { this.hidden = isHidden(); this.visibilityState = visibilityState(); fn.call(this, evt); }.bind(this), usecapture); } return undefined; } }; })(undefined);
或者直接呼叫:
<script src="http://www.zhangxinxu.com/study/201211/pageVisibility.js"></script>
其中具體細節無需關心,實際上上面這麼多程式碼本質上就是下面這點:
var pageVisibility = { hidden: Boolean visibilityState: String visibilitychange: Function };
與_原生屬性事件_對應關係如下:
pageVisibility.hidden === document.hidden(相容處理)
pageVisibility.visibilityState=== document.visibilityState(相容處理)
pageVisibility.visibilitychange(function() { /* this指的就是pageVisibility */ }); === document.addEventListener("visibilitychange", function() {});(相容處理)
於是,要判斷一個瀏覽器是否支援頁面可見性API如下程式碼就可以了(無需什麼webkit或moz或ms等字首一個個判斷了):
var isSupport = typeof pageVisibility.hidden !== "undefined"
對於不支援的瀏覽器,如IE9瀏覽器,顯示的則是”undefined
“:
OK,萬屎具備,只欠草紙了!下面,看看,頁面可見性API都有些可以有的實際應用。
//zxx: 下面為廣告~~注意不要勿點~~嘻嘻~~
五、頁面可見性API實際應用
先來看看老外給的一個例子,我覺得很有實際應用價值的。
進去後,會有一個HTML5 video顯示的Google Chrome瀏覽器廣告的30秒funny視訊,如下圖所示:
直接瀏覽你是看不出什麼玄乎的,請切換一個選項卡,讓該頁面置於後面,結果,您會發現這個選項卡的標題欄變成了這樣:
看出來沒?視訊播放被中斷了——當page不可見的時候,視訊會自動暫停!
此時,您再進入該選項卡,視訊又從剛才的地方繼續播放了,如下截圖:
個人愚見,國內的一些視訊站點是不是可以應用下這個API呢!這樣當媽媽進來送香蕉的時候,直接win+D顯示桌面就可以了,聲音啊什麼的會自動關掉,振奮視訊自動暫停,多讚的一個功能啊!以前的暫停視訊+最小化瀏覽器直接變成了一步→最小化,節約了大量的寶貴時間,極大了提升了使用者體驗,恩!不錯!!
上面的例子畢竟長在外人田啊,一旦建起了圍牆就看不到了,因此,自己折騰了一個簡單的10秒鐘低質量的貓貓版本。//zxx: 上面例子視訊3M+,我估算了下,1000次訪問的話,我勒個去,差不多3個G的流量去了,我現在每月流量都岌岌可危,因此,大家將就下下這個百來K的視訊(Chrome瀏覽器以及IE10下可訪問,或者誰給我尺寸小一點的ogv格式任意視訊,讓FireFox也能OK)~~
操作同上,進入頁面播放,離開頁面暫停。
登入同步
這是我想的一個覺得蠻實用的應用。有如下場景:
1. 去淘寶買東西,未登入狀態下,進入首頁。
2. 然後新視窗開啟任意頁面,登入併成功返回。
3. 再次訪問剛才開啟的首頁,發現頁面還是未登入狀態(見下圖),實際上使用者已經登入了。
目前,這種狀態大家似乎習以為常,覺得很OK,實際上這種糟糕的。就像沒有空調的歲月裡,人們覺得風扇很OK啊;但是,現在呢,還有誰屋頂吊個風扇嗎!!有了頁面可見性API,我們可以把體驗做地更好。
不出意外,您預設進來應該是提示你登入的:
點選上圖所示的“登入”文字連結,會在新視窗無重新整理登入。任意使用者名稱和密碼,成功後再回到之前提示的登入頁面,已經變成了:“歡迎回來,某某某”了!
只要該頁面不被關閉,你怎樣重新整理,都是“歡迎回來,某某某”。不過,在實際應用中,檢測到已經登入成功,直接重新整理當前頁面的居多!IE10下,貌似本地儲存無法同源不同頁面共享,這使得通過HTML5本地儲存共享資訊的做法遇到了些許阻礙。
精確的線上時長
這個不用多說,只有使用者當前這個頁面可見的時候,才計算線上時間,這樣可以避免掛機的情況,時長計算更準確(這個可能不是個好idea)。
線上聊天離開狀態
網頁聊天的時候,可以知道使用者是否“離開”還是“離線”還是“下線”。當前頁面不可見,但連線還在的時候,我們可以確定該人是離開的(涉及隱私,可能也不是個好idea)。
以及其他些應用需求
等到了實際需求的時候,就會想到頁面可見性API,看看能不能漸進增加下使用者體驗等。
六、結語
腦細胞不夠用了,肯定還有很多現有的可以應用在實際專案中的idea的,一時想不出——恩,比方說,每次使用者切換到你這個頁面上的時候,logo抖一下,或頁面一道亮光閃過,後者歡迎語之類……總之,是個很有用很有趣的API.
此API支援日趨穩定,不會有被去除的可能,因此,大夥兒可以放心大膽嘗試之……因為是新東西,您的任何小小idea都會是首創,領先的創造者——開動你的腦筋,發揮你的創造性思維,讓我們的網頁更加生動多彩吧!
集思廣益,歡迎補充!如有錯誤,歡迎糾正!
參考文章:
(本篇完)