Verwendung der Document Picture-in-Picture API
Experimentell: Dies ist eine experimentelle Technologie
Überprüfen Sie die Browser-Kompatibilitätstabelle sorgfältig, bevor Sie diese produktiv verwenden.
Sicherer Kontext: Diese Funktion ist nur in sicheren Kontexten (HTTPS) in einigen oder allen unterstützenden Browsern verfügbar.
Dieser Leitfaden bietet eine Anleitung zur typischen Nutzung der Document Picture-in-Picture API.
Hinweis: Sie können das vorgestellte Demo in Aktion sehen unter Document Picture-in-Picture API Example (sehen Sie sich auch den vollständigen Quellcode an).
Beispiel-HTML
Das folgende HTML richtet einen grundlegenden Videoplayer ein.
<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>
Funktionsüberprüfung
Um zu prüfen, ob die Document Picture-in-Picture API unterstützt wird, können Sie testen, ob documentPictureInPicture
auf window
verfügbar ist:
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, false);
document.getElementById("control-bar").appendChild(togglePipButton);
}
Ist es verfügbar, entfernen wir die Nachricht "Document Picture-in-Picture API not available" und fügen stattdessen ein <button>
-Element hinzu, um den Videoplayer in einem Document Picture-in-Picture-Fenster zu öffnen.
Öffnen eines Picture-in-Picture Fensters
Das folgende JavaScript ruft window.documentPictureInPicture.requestWindow()
auf, um ein leeres Picture-in-Picture-Fenster zu öffnen. Das zurückgegebene Promise
erfüllt sich mit einem Picture-in-Picture Window
Objekt. Der Videoplayer wird in dieses Fenster verschoben, indem Element.append()
verwendet wird, und wir zeigen die Nachricht an, die den Benutzer informiert, dass er verschoben wurde.
Die Optionen width
und height
von requestWindow()
setzen das Picture-in-Picture-Fenster auf die gewünschte Größe. Browser können die Optionswerte anpassen, wenn sie zu groß oder zu klein für eine benutzerfreundliche Fenstergröße sind.
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";
}
Stilvorlagen in das Picture-in-Picture Fenster kopieren
Um alle CSS-Stilvorlagen aus dem ursprünglichen Fenster zu kopieren, durchlaufen Sie alle Stilvorlagen, die explizit in das Dokument verlinkt oder eingebettet sind (über Document.styleSheets
), und hängen Sie sie an das Picture-in-Picture-Fenster an. Beachten Sie, dass dies eine einmalige Kopie ist.
// ...
// 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);
}
});
// ...
Stile im Picture-in-Picture Modus anpassen
Der picture-in-picture
Wert der display-mode
Media-Feature ermöglicht es Entwicklern, CSS auf ein Dokument anzuwenden, je nachdem, ob es im Picture-in-Picture-Modus angezeigt wird. Die grundlegende Anwendung sieht so aus:
@media (display-mode: picture-in-picture) {
body {
background: red;
}
}
Dieses Snippet macht den Hintergrund des Dokuments <body>
rot, nur wenn es im Picture-in-Picture-Modus angezeigt wird.
In unserem Demo kombinieren wir den display-mode: picture-in-picture
Wert mit dem prefers-color-scheme
Media-Feature, um helle und dunkle Farbschemas zu erzeugen, die basierend auf der Farbpräferenz des Benutzers angewendet werden, nur wenn die App im Picture-in-Picture-Modus angezeigt wird.
@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: #333;
}
a {
color: antiquewhite;
}
}
Umgang mit dem Schließen des Picture-in-Picture Fensters
Der Code zum erneuten Schließen des Picture-in-Picture Fensters, wenn der Button ein zweites Mal gedrückt wird, sieht wie folgt aus:
inPipMessage.style.display = "none";
playerContainer.append(videoPlayer);
window.documentPictureInPicture.window.close();
Hier kehren wir die DOM-Änderungen um — wir blenden die Nachricht aus und setzen den Videoplayer wieder in den Player-Container im Hauptanwendungsfenster. Wir schließen auch das Picture-in-Picture-Fenster programmatisch mit der Window.close()
Methode.
Sie müssen jedoch auch den Fall berücksichtigen, dass der Benutzer das Picture-in-Picture-Fenster schließt, indem er den vom Browser bereitgestellten Schließen (X) Knopf im Fenster selbst drückt. Dies können Sie behandeln, indem Sie feststellen, wann das Fenster geschlossen wird, indem Sie das pagehide
Ereignis erkennen:
pipWindow.addEventListener("pagehide", (event) => {
inPipMessage.style.display = "none";
playerContainer.append(videoPlayer);
});
Zuhören, wann die Website in Picture-in-Picture wechselt
Hören Sie auf das enter
Ereignis auf der DocumentPictureInPicture
Instanz, um zu wissen, wann ein Picture-in-Picture-Fenster geöffnet wird.
In unserem Demo verwenden wir das enter
Ereignis, um einen Stummschaltknopf zum Picture-in-Picture-Fenster hinzuzufügen:
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);
});
Hinweis: Das DocumentPictureInPictureEvent
Ereignisobjekt enthält eine window
Eigenschaft, um auf das Picture-in-Picture-Fenster zuzugreifen.
Zugriff auf Elemente und Umgang mit Ereignissen
Sie können auf Elemente im Picture-in-Picture-Fenster auf verschiedene Weise zugreifen:
- Die durch die
DocumentPictureInPicture.requestWindow()
Methode zurückgegebeneWindow
Instanz, wie oben gesehen. - Über die
window
Eigenschaft desDocumentPictureInPictureEvent
Ereignisobjekts (beimenter
Ereignis), wie oben gesehen. - Über die
DocumentPictureInPicture.window
Eigenschaft:
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;
}
Sobald Sie eine Referenz zur Picture-in-Picture window
Instanz haben, können Sie den DOM manipulieren (z.B. Buttons erstellen) und auf Benutzereingabeereignisse (wie click
) reagieren, wie Sie es normalerweise im regulären Browserfensterkontext tun würden.