示例 HTML
以下 HTML 設定了一個基本的影片播放器。
<div id="container">
<p class="in-pip-message">
Video player is currently in the separate Picture-in-Picture window.
</p>
<div id="player">
<video
src="assets/bigbuckbunny.mp4"
id="video"
controls
width="320"></video>
<div id="credits">
<a href="https://peach.blender.org/download/" target="_blank">
Video by Blender </a
>;
<a href="https://peach.blender.org/about/" target="_blank">
licensed CC-BY 3.0
</a>
</div>
<div id="control-bar">
<p class="no-picture-in-picture">
Document Picture-in-Picture API not available
</p>
<p></p>
</div>
</div>
</div>
特性檢測
要檢查是否支援文件畫中畫 API,您可以測試 window 上的 documentPictureInPicture 是否可用。
if ("documentPictureInPicture" in window) {
document.querySelector(".no-picture-in-picture").remove();
const togglePipButton = document.createElement("button");
togglePipButton.textContent = "Toggle Picture-in-Picture";
togglePipButton.addEventListener("click", togglePictureInPicture);
document.getElementById("control-bar").appendChild(togglePipButton);
}
如果可用,我們將移除“不支援文件畫中畫 API”的訊息,而是新增一個<button> 元素來在文件畫中畫視窗中開啟影片播放器。
開啟畫中畫視窗
以下 JavaScript 呼叫 window.documentPictureInPicture.requestWindow() 來開啟一個空白的畫中畫視窗。返回的Promise 將會成功解析為一個畫中畫Window 物件。影片播放器透過 Element.append() 方法移動到該視窗,然後我們顯示一條訊息告知使用者影片已移走。
requestWindow() 的 width 和 height 選項可將畫中畫視窗設定為所需大小。瀏覽器可能會限制選項值,如果它們太大或太小,以至於無法適應使用者友好的視窗大小。
async function togglePictureInPicture() {
// Early return if there's already a Picture-in-Picture window open
if (window.documentPictureInPicture.window) {
return;
}
// Open a Picture-in-Picture window.
const pipWindow = await window.documentPictureInPicture.requestWindow({
width: videoPlayer.clientWidth,
height: videoPlayer.clientHeight,
});
// …
// Move the player to the Picture-in-Picture window.
pipWindow.document.body.append(videoPlayer);
// Display a message to say it has been moved
inPipMessage.style.display = "block";
}
將樣式表複製到畫中畫視窗
要從原始視窗複製所有 CSS 樣式表,請遍歷所有顯式連結到或嵌入到文件中的樣式表(透過 Document.styleSheets),並將它們附加到畫中畫視窗。請注意,這只是一個一次性複製。
// …
// 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);
}
});
// …
在畫中畫模式下定位樣式
display-mode 媒體特性的 picture-in-picture 值允許開發者根據文件是否在畫中畫模式下顯示來應用 CSS。基本用法如下:
@media (display-mode: picture-in-picture) {
body {
background: red;
}
}
此程式碼片段將在文件 <body> 顯示在畫中畫模式時,將其背景變為紅色。
在我們的演示中,我們將 display-mode: picture-in-picture 值與 prefers-color-scheme 媒體特性結合使用,以建立淺色和深色配色方案,這些方案會根據使用者的顏色方案偏好進行應用,僅當應用在畫中畫模式下顯示時。
@media (display-mode: picture-in-picture) and (prefers-color-scheme: light) {
body {
background: antiquewhite;
}
}
@media (display-mode: picture-in-picture) and (prefers-color-scheme: dark) {
body {
background: #333333;
}
a {
color: antiquewhite;
}
}
處理畫中畫視窗關閉的情況
當按鈕被第二次按下時,用於關閉畫中畫視窗的程式碼如下:
inPipMessage.style.display = "none";
playerContainer.append(videoPlayer);
window.documentPictureInPicture.window.close();
這裡我們撤銷 DOM 更改——隱藏訊息並將影片播放器放回主應用程式視窗的播放器容器中。我們還使用 Window.close() 方法以程式設計方式關閉畫中畫視窗。
然而,您還需要考慮使用者透過按視窗本身的瀏覽器提供的 UI 關閉控制元件來關閉畫中畫視窗的情況。您可以透過使用 pagehide 事件檢測視窗何時關閉來處理這種情況。
pipWindow.addEventListener("pagehide", (event) => {
inPipMessage.style.display = "none";
playerContainer.append(videoPlayer);
});
注意: 透過在呼叫 DocumentPictureInPicture.requestWindow() 開啟畫中畫視窗時,在選項物件中將 disallowReturnToOpener 提示設定為 true,可以隱藏瀏覽器提供的 UI 關閉控制元件。
監聽網站進入畫中畫狀態
監聽 DocumentPictureInPicture 例項上的 enter 事件,以瞭解何時打開了畫中畫視窗。
在我們的演示中,我們使用 enter 事件將一個靜音切換按鈕新增到畫中畫視窗。
documentPictureInPicture.addEventListener("enter", (event) => {
const pipWindow = event.window;
console.log("Video player has entered the pip window");
const pipMuteButton = pipWindow.document.createElement("button");
pipMuteButton.textContent = "Mute";
pipMuteButton.addEventListener("click", () => {
const pipVideo = pipWindow.document.querySelector("#video");
if (!pipVideo.muted) {
pipVideo.muted = true;
pipMuteButton.textContent = "Unmute";
} else {
pipVideo.muted = false;
pipMuteButton.textContent = "Mute";
}
});
pipWindow.document.body.append(pipMuteButton);
});
注意: DocumentPictureInPictureEvent 事件物件包含一個 window 屬性,用於訪問畫中畫視窗。
訪問元素並處理事件
您可以透過以下幾種方式訪問畫中畫視窗中的元素:
- 如上所示,透過
DocumentPictureInPicture.requestWindow()方法返回的Window例項。 - 透過(如上所示)
enter事件中的DocumentPictureInPictureEvent事件物件的window屬性。 - 透過
DocumentPictureInPicture.window屬性。
const pipWindow = window.documentPictureInPicture.window;
if (pipWindow) {
// Mute video playing in the Picture-in-Picture window.
const pipVideo = pipWindow.document.querySelector("#video");
pipVideo.muted = true;
}
一旦您獲得了畫中畫 window 例項的引用,您就可以像在常規瀏覽器視窗環境中一樣,操作 DOM(例如建立按鈕)並響應使用者輸入事件(例如 click)。