第一次看到應用 Fullscreen API 全屏顯示網頁,是 FaceBook 中的照片放大。作為一個比較新的 API,目前只有 Safari、Chrome 和 FireFox 三種瀏覽器支援該特性。因為尚未釋出正式版的標準,所以必須使用瀏覽器特定的方法,也就是應用新增字首(webit/moz)的方法。
這個 API 不僅能夠使整個頁面全屏顯示,也可以使頁面中的某個元素全屏顯示。它的設計初衷是為了全屏顯示 HTML5 視訊和遊戲,以便更全面的替代 flash 功能。儘管還有很多有待完善的地方,但是作為一個新的瀏覽器特性,在某些地方還是能夠極大地增強使用者體驗。
1. 標準呼叫方式
要對某個元素使用全屏特效,標準的流程是:
-
呼叫這個元素物件的 requestFullscreen() 方法;
-
瀏覽器將元素全屏顯示,改變相關的屬性值,然後觸發 document 的 fullscreenchange 事件;
-
退出全屏時有兩種方式,一種是預設的按 ESC 鍵退出,一種是呼叫 document 的 exitFullscreen() 方法;
-
瀏覽器將元素退出全屏顯示,改變相關屬性值,再次觸發 fullscreenchange 方法。
瀏覽器在改變全屏狀態時修改的相關屬性,是指修改當前全屏狀態有否、全屏顯示的元素物件,這些屬性都是隻讀的。
瀏覽器觸發 fullscreenchange 事件,預設不做任何處理,內部的處理函式需要程式設計人員自行判斷當前全屏狀態後,進行相應處理。
對應的,規範中還新增了一個 :fullscreen 偽類,對當前全屏的元素進行樣式定義。
2. 封裝API
Fullscreen 目前只有兩個方法:進入全屏、退出全屏,三個屬性(全部是隻讀的):是否支援全屏、當前全屏狀態、當前全屏元素,以及一個在全屏狀態改變時觸發的事件( Using full-screen mode 中提到還有一個 fullscreenerror,但是我沒有測試出如何才能觸發這個事件 )。與 W3 草案 相比,FireFox 的實現更符合標準,而 webkit 核心瀏覽器中的方法則要自我很多。
所有的方法和屬性中,只有 requestFullscreen() 是 element 物件的方法,其他全部是 document 物件所有的方法和屬性。
2.1 進入全屏:element.requestFullscreen()
將 element 全屏顯示。webkit核心瀏覽器和Firefox表現不同,前者只要求element是DOM元素即可,後者則要求DOM必須是文件流中的元素,比較嚴格,否則不能全屏顯示。
出於安全考慮,全屏狀態下預設是不允許使用者輸入的。webkit 核心瀏覽器會阻止除方向鍵、控制鍵之外的鍵盤輸入,FireFox 會在輸入時發出要求使用者退出全屏狀態的提示。前者可以通過在方法 webkitRequestFullScreen() 中傳入引數 Element.LLOW_KEYBOARD_INPUT 允許使用者輸入,但 Safari 一旦傳入該引數,整個 Fullscreen 功能都會壞掉(這應該是 Safari 的一個bug);後者直接就可以輸入,除了有個煩人的提示。
webkit 瀏覽器中可以通過只讀屬性 document.webkitFullScreenKeyboardInputAllowed 檢視當前是否允許全屏狀態下的輸入。
/**
* 標準化 requestFullscreen 方法
* @param {DOM} elem 要全屏顯示的元素(webkit下只要是DOM即可,Firefox下必須是文件中的DOM元素)
*/
function requestFullscreen( elem ) {
if (elem.requestFullscreen) {
elem.requestFullscreen();
}
else if (elem.webkitRequestFullScreen) {
// 對 Chrome 特殊處理,
// 引數 Element.ALLOW_KEYBOARD_INPUT 使全屏狀態中可以鍵盤輸入。
if ( window.navigator.userAgent.toUpperCase().indexOf( `CHROME` ) >= 0 ) {
elem.webkitRequestFullScreen( Element.ALLOW_KEYBOARD_INPUT );
}
// Safari 瀏覽器中,如果方法內有引數,則 Fullscreen 功能不可用。
else {
elem.webkitRequestFullScreen();
}
}
else if (elem.mozRequestFullScreen) {
elem.mozRequestFullScreen();
}
}
2.2 退出全屏:document.exitFullscreen()
從全屏狀態中退出。目前實現的方法都是 cancelFullScreen() ,而不是標準的 exitFullscreen()。
/**
* 標準化 exitFullscreen 方法
*/
function exitFullscreen() {
if (document.exitFullscreen) {
document.exitFullscreen();
}
else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
}
else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
}
}
2.3 瀏覽器是否支援全屏:document.fullscreenEnabled
通過該屬性的boolean值判斷瀏覽器是支援 Fullscreen 功能。
webkit 核心的瀏覽器目前還沒有該屬性,因此只能通過能力判定來判斷是否支援全屏顯示功能。Firefox 已經有了對應的屬性定義。
/* 標準化 fullscreenEnabled 屬性 (只讀) */
document.fullscreenEnabled = ( function() {
var doc = document.documentElement;
return ( `requestFullscreen` in doc ) ||
( `webkitRequestFullScreen` in doc ) ||
// 對Firefox除了能力判斷,還加上了屬性判斷
( `mozRequestFullScreen` in doc && document.mozFullScreenEnabled ) ||
false;
} )();
2.4 :document.fullscreenElement
當前全屏顯示的DOM元素。
/**
* 標準化 fullscreenElement 屬性 (只讀)
* 以同名方法替代
*/
function fullscreenElement() {
return document.fullscreenElement ||
document.webkitCurrentFullScreenElement ||
document.mozFullScreenElement ||
null;
}
2.5 當前全屏狀態:document.fullscreen
該屬性並未在2012/6/3的 w3草案 中出現,但在Using full-screen mode 一文中介紹了該屬性。其值為 boolean 型別,判斷當前文件的全屏狀態。
如果最終去掉這個判斷全屏狀態的屬性,我們仍然可以通過 document.fullscreenElement 的值是否為 null 來判斷全屏與否
/**
* 標準化 fullscreen 屬性 (只讀)
* 以同名方法替代
*/
function fullscreen() {
return document.fullscreen ||
document.webkitIsFullScreen ||
document.mozFullScreen ||
false;
}
2.6 全屏狀態改變事件:fullscreenchange
該事件要繫結在 document 上,該事件僅在全屏狀態改變時觸發,預設沒有任何動作。
/* 繫結 document 的 fullscreenchange 事件 */
document.addEventListener(
`fullscreenchange`, // webkitfullscreenchange/mozfullscreenchange
function( evt ){
//todo 全屏狀態改變時的時間處理。
//預設不會有任何處理,需要自己判斷當前螢幕全屏與否,做出相應處理。
},
false
);
/* 如果使用 jQuery : */
$( document ).bind(
`fullscreenchange webkitfullscreenchange mozfullscreenchange`,
function(){
//todo code
}
);
3. 全屏樣式設定
標準中,通過 :fullscreen 偽類對全屏的元素進行樣式定義。
預設情況下,瀏覽器只會簡單地將元素設定為全屏顯示。如果該元素全屏後,高度比螢幕還高,超出的部分將會被隱藏。為了將超出部分可以滾動顯示,最頂層全屏顯示的元素要特別設定:
position : fixed;
top : 0;
left : 0;
width : 100%;
height : 100%;
overflow : auto;
一般情況下,要全屏顯示的元素是不能像上面這樣設定的。那麼我們可以變通下,設定一個 <div/>,包圍要全屏的元素,然後將這個 <div/> 設定為全屏,上面的樣式定義就可以定義在這個 <div/> 上,相應的,:fullscreen 將會作用在這個 <div/> 上。這樣,過長的元素就可以在這個包圍層內滾動顯示。
4. 特別注意
-
目前 FireFox 10、Safari 5.1+、Chrome 15+ 支援全屏
-
可以使任意元素全屏顯示,不只是整個頁面
-
全屏只能從事件觸發(使用者操作),而不能用程式碼直接觸發
-
全屏狀態下,webkit 核心瀏覽器預設會阻止除方向鍵、控制鍵之外的鍵盤輸入,FireFox 會在輸入時發出退出全屏狀態提示。處理方法在 封裝API 部分有說明。
下面是實際中遇到的需要注意的地方:
-
全屏狀態切換需要時間。執行 requestFullscreen() 後,並不會立即進入全屏狀態,對應的全屏屬性不會立即更改,而是有一個執行時間。因此,只能在 fullscreenchange 事件觸發後才代表進入了全屏狀態。但是在 fullscreenchange 事件中呼叫 $(window).width() 並不總能得到全屏的尺寸,這個現象很奇怪。如果需要螢幕尺寸,可以通過 window.screen.width 來獲得。
-
涉及修改DOM文件須注意程式碼位置。當用 <div/> 包圍要全屏顯示的元素時,這段 javascript 程式碼不應該在要全屏顯示的元素內部,否則這段程式碼會被執行兩遍,而且第二遍不會在斷點中被監視到,原因將在後文詳細描述。
-
ESC 鍵不同系統功能不同。目前發現點選 ESC 退出全屏時,mac系統不會再額外觸發鍵盤事件,但是win7系統下出發 fullscreenchange 事件後還會立馬觸發鍵盤事件,因此如果還有不希望被觸發的鍵盤事件,可以設定一個監視變數,在很短時間後再修改監視變數,以錯過這個立馬執行的時間。
5. 未涉及功能
-
iframe 元素的 allowfullscreen 屬性
-
::backdrop 偽類
-
具體其他細節可以參考 W3 草案
6. 結語
Fullscreen API 畢竟目前只是草案,尚未形成正式的標準,況且各個瀏覽器的實現情況也不完全相同,甚至細節上的實現差別更可能引發預想不到的問題。但作為漸進增強方式使用的新功能,能夠極大的增強使用者體驗。仍要根據規範的完善,不斷改進我們的程式碼。
詳細程式碼可以參考:https://github.com/calefy/calefy.github.com/blob/master/js/Fullscreen.js
參考
-
程式碼參考 jQuery Fullscreen 外掛