Bild im Bild für jedes Element, nicht nur <Video>

François Beaufort
François Beaufort

Browser Support

  • Chrome: 116.
  • Edge: 116.
  • Firefox: not supported.
  • Safari: not supported.

Source

Mit der Document Picture-in-Picture API lässt sich ein Fenster öffnen, das immer im Vordergrund angezeigt wird und mit beliebigem HTML-Inhalt gefüllt werden kann. Sie erweitert die vorhandene Bild-im-Bild-API für <video>, mit der nur ein HTML-<video>-Element in ein Bild-im-Bild-Fenster eingefügt werden kann.

Das Bild-im-Bild-Fenster in der Document Picture-in-Picture API ähnelt einem leeren Fenster mit demselben Ursprung, das über window.open() geöffnet wird, weist jedoch einige Unterschiede auf:

  • Das Fenster für „Bild im Bild“ wird über anderen Fenstern angezeigt.
  • Das Bild-im-Bild-Fenster wird nie länger als das ursprüngliche Fenster angezeigt.
  • Das Bild-im-Bild-Fenster kann nicht bedient werden.
  • Die Position des Bild-im-Bild-Fensters kann nicht von der Website festgelegt werden.
Ein Bild-im-Bild-Fenster, in dem der Trailer zu „Sintel“ abgespielt wird.
Ein Bild-im-Bild-Fenster, das mit der Document Picture-in-Picture API (Demo) erstellt wurde.

Aktueller Status

Schritt Status
1. Erklärung erstellen Abschließen
2. Ersten Entwurf der Spezifikation erstellen In Bearbeitung
3. Feedback einholen und Design iterieren In Bearbeitung
4. Ursprungstest Abschließen
5. Starten Abgeschlossen (Desktop)

Anwendungsfälle

Benutzerdefinierter Videoplayer

Eine Website kann mit der vorhandenen Picture-in-Picture API für <video> eine Bild-im-Bild-Videowiedergabe ermöglichen. Diese API ist jedoch sehr eingeschränkt. Das vorhandene Bild-im-Bild-Fenster akzeptiert nur wenige Eingaben und bietet nur begrenzte Möglichkeiten, sie zu gestalten. Mit einem vollständigen Dokument im Bild-im-Bild-Modus kann die Website benutzerdefinierte Steuerelemente und Eingaben (z. B. Untertitel, Playlists, Zeitleiste, Liken und Disliken von Videos) bereitstellen, um die Video-Wiedergabe im Bild-im-Bild-Modus zu verbessern.

Videokonferenzsysteme

Es ist üblich, dass Nutzer den Browser-Tab während einer Videokonferenz aus verschiedenen Gründen verlassen (z. B. um einen anderen Tab in der Videokonferenz zu präsentieren oder um Multitasking zu betreiben), aber trotzdem die Videokonferenz sehen möchten. Dies ist also ein idealer Anwendungsfall für „Bild im Bild“. Auch hier ist die aktuelle Erfahrung, die eine Videokonferenzwebsite über die Bild-im-Bild-API für <video> bieten kann, in Bezug auf Stil und Eingabe begrenzt. Mit einem vollständigen Dokument im Bild-im-Bild-Modus kann die Website mehrere Videostreams ganz einfach in einem einzigen BiB-Fenster kombinieren, ohne auf Canvas-Hacks angewiesen zu sein. Außerdem können benutzerdefinierte Steuerelemente wie das Senden einer Nachricht, das Stummschalten eines anderen Nutzers oder das Melden von Interesse bereitgestellt werden.

Produktivität

Untersuchungen haben ergeben, dass Nutzer mehr Möglichkeiten benötigen, um im Web produktiv zu sein. Mit der Funktion „Dokument im Bild im Bild“ können Web-Apps mehr leisten. Ob es sich um Textbearbeitung, Notizen, Aufgabenlisten, Messaging und Chat oder Design- und Entwicklungstools handelt – Web-Apps können ihre Inhalte jetzt immer zugänglich halten.

Schnittstelle

Attribute

documentPictureInPicture.window
Gibt das aktuelle „Bild im Bild“-Fenster zurück, falls vorhanden. Andernfalls wird null zurückgegeben.

Methoden

documentPictureInPicture.requestWindow(options)

Gibt ein Promise zurück, das aufgelöst wird, wenn ein Bild-im-Bild-Fenster geöffnet wird. Das Promise wird abgelehnt, wenn es ohne Nutzeraktion aufgerufen wird. Das options-Wörterbuch enthält die folgenden optionalen Elemente:

width
Legt die anfängliche Breite des Fensters für „Bild im Bild“ fest.
height
Legt die anfängliche Höhe des Fensters für „Bild im Bild“ fest.
disallowReturnToOpener
Wenn „true“ festgelegt ist, wird die Schaltfläche „Zurück zum Tab“ im Bild-im-Bild-Fenster ausgeblendet. Der Standardwert ist „false“.
preferInitialWindowPlacement
Das Bild-im-Bild-Fenster wird in der Standardposition und ‑größe geöffnet, wenn „true“ festgelegt ist. Der Standardwert ist „false“.

Ereignisse

documentPictureInPicture.onenter
Wird auf documentPictureInPicture ausgelöst, wenn ein Bild-im-Bild-Fenster geöffnet wird.

Beispiele

Mit dem folgenden HTML-Code wird ein benutzerdefinierter Videoplayer und ein Schaltflächenelement eingerichtet, um den Videoplayer in einem Bild-im-Bild-Fenster zu öffnen.

<div id="playerContainer">
  <div id="player">
    <video id="video"></video>
  </div>
</div>
<button id="pipButton">Open Picture-in-Picture window</button>

Bild-im-Bild-Fenster öffnen

Mit dem folgenden JavaScript wird documentPictureInPicture.requestWindow() aufgerufen, wenn der Nutzer auf die Schaltfläche klickt, um ein leeres Bild-im-Bild-Fenster zu öffnen. Das zurückgegebene Promise wird mit einem JavaScript-Objekt für das Bild-im-Bild-Fenster aufgelöst. Der Videoplayer wird mit append() in dieses Fenster verschoben.

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);
});

Größe des Bild-im-Bild-Fensters festlegen

Wenn Sie die Größe des Bild-im-Bild-Fensters festlegen möchten, legen Sie die Optionen width und height von documentPictureInPicture.requestWindow() auf die gewünschte Größe des Bild-im-Bild-Fensters fest. Chrome kann die Optionswerte begrenzen, wenn sie zu groß oder zu klein sind, um in eine benutzerfreundliche Fenstergröße zu passen.

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);
});

Schaltfläche „Zurück zum Tab“ im Fenster für „Bild im Bild“ ausblenden

Wenn Sie die Schaltfläche im Bild-im-Bild-Fenster ausblenden möchten, über die der Nutzer zum Tab mit dem Opener zurückkehren kann, legen Sie die Option disallowReturnToOpener von documentPictureInPicture.requestWindow() auf true fest.

pipButton.addEventListener("click", async () => {
  // Open a Picture-in-Picture window which hides the "back to tab" button.
  const pipWindow = await documentPictureInPicture.requestWindow({
    disallowReturnToOpener: true,
  });
});

Bild-im-Bild-Fenster in der Standardposition und ‑größe öffnen

Wenn Sie die Position oder Größe des vorherigen „Bild im Bild“-Fensters nicht wiederverwenden möchten, setzen Sie die Option preferInitialWindowPlacement von documentPictureInPicture.requestWindow() auf true.

pipButton.addEventListener("click", async () => {
  // Open a Picture-in-Picture window in its default position / size.
  const pipWindow = await documentPictureInPicture.requestWindow({
    preferInitialWindowPlacement: true,
  });
});

Stylesheets in das Bild-im-Bild-Fenster kopieren

Um alle CSS-Stylesheets aus dem ursprünglichen Fenster zu kopieren, durchlaufen Sie styleSheets, die explizit mit dem Dokument verknüpft oder darin eingebettet sind, und hängen Sie sie an das Bild-im-Bild-Fenster an. Beachten Sie, dass es sich um ein einmaliges Kopieren handelt.

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);
});

Umgang mit dem Schließen des Bild-im-Bild-Fensters

Mit dem "pagehide"-Ereignis des Fensters können Sie erkennen, wann das Bild-im-Bild-Fenster geschlossen wird (entweder weil die Website es initiiert hat oder der Nutzer es manuell geschlossen hat). Der Event-Handler ist ein guter Ort, um die Elemente wieder aus dem Bild-im-Bild-Fenster zu holen, wie hier gezeigt.

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);
  });
});

Schließen Sie das Bild-im-Bild-Fenster programmatisch mit der Methode close().

// Close the Picture-in-Picture window programmatically. 
// The "pagehide" event will fire normally.
pipWindow.close();

Wenn die Website in den Bild-im-Bild-Modus wechselt

Mit dem "enter"-Ereignis für documentPictureInPicture können Sie erkennen, wann ein Bild-im-Bild-Fenster geöffnet wird. Das Ereignis enthält ein window-Objekt für den Zugriff auf das Bild-im-Bild-Fenster.

documentPictureInPicture.addEventListener("enter", (event) => {
  const pipWindow = event.window;
});

Auf Elemente im Bild-im-Bild-Fenster zugreifen

Sie können auf Elemente im Bild-im-Bild-Fenster entweder über das von documentPictureInPicture.requestWindow() zurückgegebene Objekt oder mit documentPictureInPicture.window zugreifen, wie unten gezeigt.

const pipWindow = documentPictureInPicture.window;
if (pipWindow) {
  // Mute video playing in the Picture-in-Picture window.
  const pipVideo = pipWindow.document.querySelector("#video");
  pipVideo.muted = true;
}

Ereignisse aus dem Bild-im-Bild-Fenster verarbeiten

Sie können Schaltflächen und Steuerelemente erstellen und auf Nutzereingabeereignisse wie "click" reagieren, wie Sie es normalerweise in JavaScript tun würden.

// Add a "mute" button to the Picture-in-Picture window.
const pipMuteButton = pipWindow.document.createElement("button");
pipMuteButton.textContent = "Mute";
pipMuteButton.addEventListener("click", () => { 
  const pipVideo = pipWindow.document.querySelector("#video");
  pipVideo.muted = true;
});
pipWindow.document.body.append(pipMuteButton);

Größe des Fensters für „Bild im Bild“ anpassen

Verwenden Sie die Fenstermethoden resizeBy() und resizeTo(), um die Größe des Fensters für „Bild im Bild“ anzupassen. Für beide Methoden ist eine Nutzeraktion erforderlich.

const resizeButton = pipWindow.document.createElement('button');
resizeButton.textContent = 'Resize';
resizeButton.addEventListener('click', () => {
  // Expand the Picture-in-Picture window's width by 20px and height by 30px.
  pipWindow.resizeBy(20, 30);
});
pipWindow.document.body.append(resizeButton);

Fokus auf das Fenster mit dem Link setzen

Verwenden Sie die focus()-Fenstermethode, um das Fenster des Öffners über das Bild-im-Bild-Fenster zu fokussieren. Für diese Methode ist eine Nutzeraktion erforderlich.

const returnToTabButton = pipWindow.document.createElement("button");
returnToTabButton.textContent = "Return to opener tab";
returnToTabButton.addEventListener("click", () => {
  window.focus();
});
pipWindow.document.body.append(returnToTabButton);

Bild-im-Bild-Anzeigemodus für Preisvergleichsportale

Mit dem CSS-Anzeigemodus picture-in-picture können Sie spezifische CSS-Regeln schreiben, die nur angewendet werden, wenn (ein Teil der) Web-App im Bild-im-Bild-Modus angezeigt wird.

@media all and (display-mode: picture-in-picture) {
  body {
    margin: 0;
  }
  h1 {
    font-size: 0.8em;
  }
}

Funktionserkennung

So prüfen Sie, ob die Document Picture-in-Picture API unterstützt wird:

if ('documentPictureInPicture' in window) {
  // The Document Picture-in-Picture API is supported.
}

Demos

VideoJS-Player

Sie können die Document Picture-in-Picture API mit der VideoJS-Player-Demo ausprobieren.

Pomodoro

Tomodoro, eine Pomodoro-Web-App, nutzt die Document Picture-in-Picture API ebenfalls, sofern verfügbar. GitHub-Pull-Anfrage ansehen

Tomodoro, eine Pomodoro-Web-App.
Ein Bild-im-Bild-Fenster in Tomodoro.

Feedback geben

Melden Sie Probleme auf GitHub, wenn Sie Vorschläge oder Fragen haben.