我第一次對網頁全屏模式有概念,是那種網頁播放視訊的全屏播 放的那種。感覺很強,前幾個星期有個需求也是關於全屏模式的,接觸之後才知道全屏模式並不神祕,是個很容易掌握的技能...
CodePen Demo
進去看看,玩一下,本文將結合這個demo一起進行講解。
全屏功能封裝在一個類裡面:
我把全屏模式封裝在一個類裡面,在程式碼中有詳細的註釋,如果有需要的話,直接把類拿出來,根據栗子和註釋使用即可。
程式碼在codepen的demo裡。
何謂全屏?
MDN介紹:
使用提供的API,讓一個元素與其子元素,可以佔據整個螢幕,並在此期間,從螢幕上隱藏所有的瀏覽器使用者介面以及其他應用。
chrome下的全屏表現:
-
全屏會隱藏標籤欄,書籤欄
-
如果網頁一開始不是全部撐開的形式,全屏下,也會將要全屏的元素充滿整個螢幕
-
可以多層全屏,如栗子中一樣,可以先左邊全屏,然後紅色全屏。
在這種情況下退出全屏,只會退出紅色全屏,退回到左邊全屏的形式,所以頁面依然是全屏模式。
-
進入全屏時,有一個預設的提示:'按esc即可退出全屏模式',如下圖顯示:
-
當按
Esc
或呼叫退出全屏方法,退出全屏。標籤欄和書籤欄依然是隱藏的,網頁上的元素恢復成原本的尺寸。要顯示書籤欄和標籤欄,需要重新整理一下頁面。
全屏API:
總共用到6個API:
- 瀏覽器是否支援全屏模式:
document.fullscreenEnabled
- 使元素進入全屏模式:
Element.requestFullscreen()
- 退出全屏:
document.exitFullscreen()
- 檢查當前是否有節點處於全屏狀態:
document.fullscreenElement
- 進入全屏/離開全屏,觸發事件:
document.fullscreenchange
- 無法進入全屏時觸發:
document.fullscreenerror
瀏覽器字首:
目前並不是所有的瀏覽器都實現了API的無字首版本,所以我們需要針對不同瀏覽器,做一下API的相容:
這是我在demo中做的瀏覽器相容:
/**
* @description: 是否支援全屏+判斷瀏覽器字首
* @param {Function} fn 不支援全屏的回撥函式 這裡設了一個預設值
*/
isFullscreen(fn) {
let fullscreenEnabled;
// 判斷瀏覽器字首
if (document.fullscreenEnabled) {
fullscreenEnabled = document.fullscreenEnabled;
} else if (document.webkitFullscreenEnabled) {
fullscreenEnabled = document.webkitFullscreenEnabled;
this.prefixName = 'webkit';
} else if (document.mozFullScreenEnabled) {
fullscreenEnabled = document.mozFullScreenEnabled;
this.prefixName = 'moz';
} else if (document.msFullscreenEnabled) {
fullscreenEnabled = document.msFullscreenEnabled;
this.prefixName = 'ms';
}
if (!fullscreenEnabled) {
if (fn !== undefined) fn(); // 執行不支援全屏的回撥
this.isFullscreenData = false;
}
}
複製程式碼
我在例項化的時候進行一次判斷瀏覽器是否支援全屏,然後儲存瀏覽器字首。
推薦這麼做,因為如果每個API都要這樣重複的判斷瀏覽器字首,那也太噁心了!
1. 瀏覽器是否支援全屏模式:document.fullscreenEnabled
document.fullscreenEnabled
屬性返回一個布林值,表示當前文件是否可以切換到全屏狀態。
程式碼在上方瀏覽器字首程式碼中給出了。
如果沒有儲存瀏覽器字首的話,注意做一下不同瀏覽器字首的相容!下面不再強調。
2. 使元素進入全屏模式:Element.requestFullscreen()
/**
* @description: 將傳進來的元素全屏
* @param {String} domName 要全屏的dom名稱
*/
Fullscreen(domName) {
const element = document.querySelector(domName); // 獲取dom
const methodName =
this.prefixName === ''
? 'requestFullscreen'
: `${this.prefixName}RequestFullScreen`; // API字首
element[methodName](); // 呼叫全屏
}
複製程式碼
這就是我們實現全屏的API,是不是超簡單?
值得注意的是:呼叫此API並不能保證元素一定能夠進入全屏模式
-
MDN:例如
<iframe>
元素具有 allowfullscreen 屬性,可選擇是否將其內容以全屏模式顯示這種不被允許全屏的元素屬於極少數情況,我試過可以將
button
全屏。 -
全屏請求必須在事件處理函式(
點選事件等
)中呼叫,否則將會被拒絕。在demo中有演示,初始化直接全屏,會觸發進入全屏失敗回撥。
3. 退出全屏:document.exitFullscreen()
介紹:
exitFullscreen() {
const methodName =
this.prefixName === ''
? 'exitFullscreen'
: `${this.prefixName}ExitFullscreen`; // API 字首
document[methodName](); // 呼叫
}
複製程式碼
呼叫這個方法會讓文件回退到上一個呼叫Element.requestFullscreen()方法進入全屏模式之前的狀態。
多層全屏
像demo中,先進入左邊全屏,再進入紅色全屏,即為:多層全屏的情況(雖然這種情況並不多)。
當出現多層全屏的情況,需要一層層的退出到頁面最初始的情況,並不是呼叫一次document.exitFullscreen()
就恢復到頁面最初始的樣子。
4. 檢查當前是否有節點處於全屏狀態:document.fullscreenElement
fullscreenElement屬性返回正處於全屏狀態的Element節點,如果當前沒有節點處於全屏狀態,則返回null
/**
* @description: 檢測有沒有元素處於全屏狀態
* @return 布林值
*/
isElementFullScreen() {
const fullscreenElement =
document.fullscreenElement ||
document.msFullscreenElement ||
document.mozFullScreenElement ||
document.webkitFullscreenElement; // 有字首的f是大寫,沒字首是小寫
if (fullscreenElement === null) {
return false; // 當前沒有元素在全屏狀態
} else {
return true; // 有元素在全屏狀態
}
}
複製程式碼
事實上,還有一個屬性document.fullscreen
,返回一個布林值,表示文件是否處於全屏模式。
兩個方法效果是一樣,但因為IE不支援這個屬性,所以這裡用的是document.fullscreenElement
5. 進入全屏/離開全屏,觸發事件:document.fullscreenchange
當我們進入全屏和離開全屏的時候,都會觸發一個fullscreenchange
事件。
MDN注意:此事件不會提供任何資訊,表明是進入全屏或退出全屏。
看了好久事件返回的資訊,確實找不到一個值,表明這是在進入全屏,或者離開全屏!
可以說相當不人性化了!但我們可以通過檢查當前是否有節點處於全屏狀態,判斷當前是否處於全屏模式。
/**
* @description: 監聽進入/離開全屏
* @param {Function} enter 進入全屏的回撥
* @param {Function} quit 離開全屏的回撥
*/
screenChange(enter,quit) {
if (!this.isFullscreenData) return;
const methodName = `on${this.prefixName}fullscreenchange`;
document[methodName] = e => {
if (this.isElementFullScreen()) {
enter && enter(e); // 進入全屏回撥
} else {
quit && quit(e); // 離開全屏的回撥
}
};
}
複製程式碼
注意:多層全屏的情況
- 先進入左邊全屏(進入全屏回撥),再進入紅色全屏(進入全屏回撥)
- 退出全屏,此時退出紅色全屏,左邊仍是全屏(觸發進入全屏回撥)
- 出現這種情況,可以在點選按鈕的時候,做一些狀態限制。或者根據全屏事件返回的dom資訊來進行判斷。
6. 無法進入全屏時觸發: document.fullscreenerror
進入全屏並不總是成功的,可能是技術原因,也可能是使用者拒絕,我們在上文進入全文的APIElement.requestFullscreen()
部分講過了。
比如全屏請求不是在事件處理函式中呼叫,會在這裡攔截到錯誤
/**
* @description: 瀏覽器無法進入全屏時觸發
* @param {Function} enterErrorFn 回撥
*/
screenError(enterErrorFn) {
const methodName = `on${this.prefixName}fullscreenerror`;
document[methodName] = e => {
enterErrorFn && enterErrorFn(e)
};
}
複製程式碼
Css: 全屏模式下的樣式
chorme 70 下的預設會為正在全屏的dom新增兩個class:稍微看一下
- 預設設定黑色背景
:not(:root):-webkit-full-screen::backdrop {
position: fixed;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
background: black; // 會將背景設為黑色的 如果你沒為你的dom設定背景的話,全屏下會為黑色
}
複製程式碼
- 預設樣式:
:not(:root):-webkit-full-screen {
object-fit: contain;
position: fixed !important;
top: 0px !important;
right: 0px !important;
bottom: 0px !important;
left: 0px !important;
box-sizing: border-box !important;
min-width: 0px !important;
max-width: none !important;
min-height: 0px !important;
max-height: none !important;
width: 100% !important;
height: 100% !important;
transform: none !important;
margin: 0px !important;
}
複製程式碼
全屏狀態的CSS:
全屏狀態下,大多數瀏覽器的CSS支援:full-screen偽類,只有IE11支援:fullscreen偽類。使用這個偽類,可以對全屏狀態設定單獨的CSS屬性。
以下css摘自阮一峰老師的Fullscreen API:全屏操作
/* 針對dom的全屏設定 */
.div:-webkit-full-screen {
background: #fff;
}
/* 全屏屬性 */
:-webkit-full-screen {}
:-moz-full-screen {}
:-ms-fullscreen {}
/* 全屏偽類 當前chrome:70 不支援 */
:full-screen {
}
:fullscreen {
/* IE11支援 */
}
複製程式碼
結語
我們可以把全屏技術應用在H5遊戲、資訊流網站、視訊等地方,下次再有全屏需求時,記住不要慌,回頭看看過本文的栗子,把我封裝的類拿出來直接用就可以啦!
希望看完的朋友可以點個喜歡/關注,您的支援是對我最大的鼓勵。
以上2018.12.1
參考資料: