【資訊】1795- Chrome 116:網(wǎng)頁畫中畫 API 來了!
Chrome 116 剛剛發(fā)布了正式版本,其中比較值得關(guān)注的新增功能就是網(wǎng)頁的畫中畫 API 了(Document Picture in Picture API )。
簡介
畫中畫 API 可以打開一個始終位于當(dāng)前網(wǎng)頁頂部的窗口,這個窗口可以填充任意的 HTML 內(nèi)容。它擴展了現(xiàn)有的 Picture-in-Picture API for <video> (其只允許將 <video> 元素放入畫中畫窗口中)。
通過 Document Picture-in-Picture API 創(chuàng)建的 Picture-in-Picture 窗口其實很類似于通過 window.open() 打開的空白的同源窗口,但也存在一些差異:
-
畫中畫窗口永遠(yuǎn)會浮動在其他窗口之上。 -
當(dāng)前窗口關(guān)閉后會立即關(guān)閉打開的畫中畫窗口 -
無法通過地址導(dǎo)航到畫中畫窗口。 -
畫中畫窗口的位置無法由網(wǎng)站設(shè)置。
使用場景
這個 API 還是有挺多實用場景的,首先我們還是可以用它來實現(xiàn)自定義視頻播放器,雖然現(xiàn)有的 Picture-in-Picture API for <video> 也可以實現(xiàn),但是效果非常有限(參數(shù)少,樣式設(shè)置靈活)?,F(xiàn)在通過新的畫中畫 API,網(wǎng)站可以提供一些自定義組件和參數(shù)(例如字幕、播放列表、時間控制、喜歡和不喜歡的視頻),來改善用戶的畫中畫視頻體驗。另外我們還可以用它來實現(xiàn)一個體驗非常好的網(wǎng)頁視頻會議功能等等。
用法
屬性
documentPictureInPicture.window:返回當(dāng)前的畫中畫窗口,如果不存在則返回 null。
方法
documentPictureInPicture.requestWindow(options):返回一個在畫中畫窗口打開時解析的 Promise 。如果在沒有用戶同意的情況下調(diào)用它, Promise 將被拒絕。options 包括兩個參數(shù):
-
width:設(shè)置畫中畫窗口的初始寬度。 -
height:設(shè)置畫中畫窗口的初始高度。
事件
documentPictureInPicture.onenter:documentPictureInPicture 打開畫中畫窗口時觸發(fā)。
例子
手下我們通過下面的 HTML 設(shè)置自定義視頻播放器和按鈕元素以在畫中畫窗口中打開視頻播放器。
<div id="playerContainer">
<div id="player">
<video id="video"></video>
</div>
</div>
<button id="pipButton">打開畫中畫窗口!</button>
打開畫中畫窗口
當(dāng)用戶單擊按鈕打開空白的畫中畫窗口時,下面的 JavaScript 會調(diào)用documentPictureInPicture.requestWindow(),然后返回的 promise 使用一個畫中畫窗口 JavaScript 對象進(jìn)行解析。然后使用 append() 將視頻播放器移動到該窗口。
pipButton.addEventListener('click', async () => {
const player = document.querySelector("#player");
// Open a Picture-in-Picture window.
const pipWindow = await documentPictureInPicture.requestWindow();
// Move the player to the Picture-in-Picture window.
pipWindow.document.body.append(player);
});
設(shè)置畫中畫窗口的大小
我們可以通過 width 和 height 屬性來設(shè)置畫中畫窗口的大小。(如果選項值太大或太小而無法適應(yīng)用戶友好的窗口大小,Chrome 可能會限制選項值)
pipButton.addEventListener("click", async () => {
const player = document.querySelector("#player");
// Open a Picture-in-Picture window whose size is
// the same as the player's.
const pipWindow = await documentPictureInPicture.requestWindow({
width: player.clientWidth,
height: player.clientHeight,
});
// Move the player to the Picture-in-Picture window.
pipWindow.document.body.append(player);
});
將樣式表復(fù)制到畫中畫窗口
要從原始窗口復(fù)制所有 CSS 樣式表,我們可以循環(huán)遍歷 styleSheets 文檔中顯式鏈接或嵌入的 CSS 樣式表,并將它們附加到畫中畫窗口。
pipButton.addEventListener("click", async () => {
const player = document.querySelector("#player");
// Open a Picture-in-Picture window.
const pipWindow = await documentPictureInPicture.requestWindow();
// Copy style sheets over from the initial document
// so that the player looks the same.
[...document.styleSheets].forEach((styleSheet) => {
try {
const cssRules = [...styleSheet.cssRules].map((rule) => rule.cssText).join('');
const style = document.createElement('style');
style.textContent = cssRules;
pipWindow.document.head.appendChild(style);
} catch (e) {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.type = styleSheet.type;
link.media = styleSheet.media;
link.href = styleSheet.href;
pipWindow.document.head.appendChild(link);
}
});
// Move the player to the Picture-in-Picture window.
pipWindow.document.body.append(player);
});
畫中畫窗口關(guān)閉時的處理
我們可以偵聽窗口的 "pagehide" 事件來了解畫中畫窗口的關(guān)閉時機(網(wǎng)站啟動它或用戶手動關(guān)閉它)。事件處理程序是將元素從畫中畫窗口中取出的好地方,如下所示。
pipButton.addEventListener("click", async () => {
const player = document.querySelector("#player");
// Open a Picture-in-Picture window.
const pipWindow = await documentPictureInPicture.requestWindow();
// Move the player to the Picture-in-Picture window.
pipWindow.document.body.append(player);
// Move the player back when the Picture-in-Picture window closes.
pipWindow.addEventListener("pagehide", (event) => {
const playerContainer = document.querySelector("#playerContainer");
const pipPlayer = event.target.querySelector("#player");
playerContainer.append(pipPlayer);
});
});
使用 close() 方法可以直接關(guān)閉畫中畫窗口。
// Close the Picture-in-Picture window programmatically.
// The "pagehide" event will fire normally.
pipWindow.close();
監(jiān)聽網(wǎng)站何時進(jìn)入畫中畫
我們可以監(jiān)聽 documentPictureInPicture 的 "enter" 事件來感知畫中畫窗口何時打開。這個事件包含一個用于訪問畫中畫窗口的 window 對象。
documentPictureInPicture.addEventListener("enter", (event) => {
const pipWindow = event.window;
});
訪問畫中畫窗口中的元素
我們可以從 documentPictureInPicture. requestwindow() 返回的對象或使用 documentPictureInPicture 訪問畫中畫窗口中的元素:
const pipWindow = documentPictureInPicture.window;
if (pipWindow) {
// Mute video playing in the Picture-in-Picture window.
const pipVideo = pipWindow.document.querySelector("#video");
pipVideo.muted = true;
}
檢查網(wǎng)站是否支持
要檢查是否支持文檔畫中畫 API,可以使用:
if ('documentPictureInPicture' in window) {
// The Document Picture-in-Picture API is supported.
}
最后
參考:
-
https://developer.chrome.com/docs/web-platform/document-picture-in-picture -
https://developer.chrome.com/blog/watch-video-using-picture-in-picture/ -
https://developer.mozilla.org/docs/Web/API/Window/open -
https://developer.mozilla.org/docs/Web/API/Element/append -
https://lazy-guy.github.io/tomodoro/index.html
回復(fù)“加群”,一起學(xué)習(xí)進(jìn)步
