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

François Beaufort
François Beaufort

Unterstützte Browser

  • 116
  • 116
  • x
  • x

Quelle

Die Document Picture-in-Picture API ermöglicht es, ein Always-On-Fenster zu öffnen, das mit beliebigem HTML-Inhalt ausgefüllt werden kann. Sie erweitert die bestehende Bild-im-Bild-API für <video>, die nur das Einfügen eines HTML-<video>-Elements in ein Bild-im-Bild-Fenster zulässt.

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

  • Das Bild-im-Bild-Fenster schwebt über anderen Fenstern.
  • Das Bild-im-Bild-Fenster überdauert nie das öffnende Fenster.
  • Im Bild-im-Bild-Fenster ist keine Navigation möglich.
  • Die Bild-im-Bild-Fensterposition kann nicht von der Website festgelegt werden.
Ein Bild-im-Bild-Fenster, in dem ein Sintel-Trailervideo abgespielt wird.
Ein Bild-im-Bild-Fenster, das mit der Dokument-Bild-im-Bild-API erstellt wurde (Demo).

Aktueller Status

Step Status
1. Erklärende 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 (Computer)

Anwendungsfälle

Benutzerdefinierter Videoplayer

Mit der bestehenden Bild-im-Bild-API für <video> können Websites auch Bild-im-Bild-Videos nutzen. Das Angebot ist jedoch sehr eingeschränkt. Für das bestehende Bild-im-Bild-Fenster sind nur wenige Eingaben möglich und es lassen sich diese nur eingeschränkt gestalten. Bei einem vollständigen Dokument im Bild-im-Bild-Format können auf der Website benutzerdefinierte Steuerelemente und Eingaben bereitgestellt werden, z. B. Untertitel, Playlists, Zeit-Scrubber sowie Videos mit „Mag ich“- oder „Mag ich nicht“-Bewertungen, um die Funktion „Bild im Bild“ für Nutzer zu verbessern.

Videokonferenzsysteme

Es kommt häufig vor, dass Nutzer während einer Videokonferenz den Browser-Tab verlassen, z. B. weil sie beim Anruf einen anderen Tab präsentieren oder weil sie den Anruf trotzdem sehen möchten. Daher ist diese Funktion ein besonders wichtiger Anwendungsfall für die Funktion „Bild im Bild“. Auch hier sind der Stil und die Eingabemöglichkeiten, die derzeit auf einer Videokonferenz-Website über die Picture-in-Picture API für <video> möglich sind, eingeschränkt. Mit einem vollständigen Dokument im Bild-im-Bild-Format lassen sich auf der Website ganz einfach mehrere Videostreams in einem einzigen BiB-Fenster kombinieren, ohne auf Canvas-Hacks zurückgreifen zu müssen. Außerdem stehen benutzerdefinierte Steuerelemente zur Verfügung, wie das Senden einer Nachricht, das Stummschalten eines anderen Nutzers oder das Melden.

Produktivität

Untersuchungen haben gezeigt, dass Nutzer mehr Möglichkeiten benötigen, im Internet produktiv zu arbeiten. Die Funktion „Im Bild im Bild“ bietet Web-Apps die Flexibilität, mehr zu erreichen. Ob Textbearbeitung, Notizen, Aufgabenlisten, Messaging- und Chat-Programme oder Design- und Entwicklungstools – Web-Apps sorgen dafür, dass Inhalte immer verfügbar sind.

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 Versprechen lehnt ab, wenn es ohne eine Nutzergeste aufgerufen wird. Das Wörterbuch options enthält die optionalen Elemente:

width
Legt die anfängliche Breite des Bild-im-Bild-Fensters fest.
height
Legt die anfängliche Höhe des Bild-im-Bild-Fensters fest.
disallowReturnToOpener
Wenn der Wert auf „true“ gesetzt ist, wird die Schaltfläche „Zurück zum Tab“ im Fenster „Bild im Bild“ ausgeblendet. Der Standardwert ist „false“.

Veranstaltungen

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

Beispiele

Mit dem folgenden HTML-Code werden ein benutzerdefinierter Videoplayer und ein Schaltflächenelement zum Öffnen des Videoplayers in einem Bild-im-Bild-Fenster eingerichtet.

<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 mithilfe von 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

Um die Größe des Bild-im-Bild-Fensters festzulegen, lege die Optionen width und height von documentPictureInPicture.requestWindow() auf die gewünschte Bild-im-Bild-Fenstergröße fest. Chrome klemmt die Optionswerte möglicherweise, wenn sie zu groß oder zu klein für eine nutzerfreundliche Fenstergröße sind.

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 Bild-im-Bild-Fenster ausblenden

Wenn die Schaltfläche im Bild-im-Bild-Fenster ausgeblendet werden soll, über die der Nutzer zum geöffneten Tab zurückkehren kann, setze die disallowReturnToOpener-Option von documentPictureInPicture.requestWindow() auf true.

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

Stylesheets in das Bild-im-Bild-Fenster kopieren

Wenn Sie alle CSS-Stylesheets aus dem ursprünglichen Fenster kopieren möchten, durchlaufen Sie styleSheets, die explizit mit dem Dokument verknüpft oder darin eingebettet sind, und hängen Sie die Elemente an das Bild-im-Bild-Fenster an. Beachten Sie, dass dies eine einmalige Kopie ist.

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

Beobachten Sie das Ereignis „Fenster "pagehide"“, um zu erfahren, wann das Bild-im-Bild-Fenster geschlossen wird (entweder weil es von der Website oder vom Nutzer manuell geschlossen wurde). Der Ereignis-Handler eignet sich gut, um die Elemente wie unten dargestellt wieder aus dem Bild-im-Bild-Fenster zu entfernen.

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 mithilfe der Methode close().

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

Anhören, wenn die Website in den Bild-im-Bild-Modus wechselt

Beobachten Sie das Ereignis "enter" auf documentPictureInPicture, um zu erfahren, 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 zugreifen, entweder über das von documentPictureInPicture.requestWindow() zurückgegebene Objekt oder mit documentPictureInPicture.window, wie unten dargestellt.

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 im Bild-im-Bild-Fenster verarbeiten

Erstellen Sie Schaltflächen und Steuerelemente und reagieren Sie wie gewohnt auf Eingabeereignisse des Nutzers wie "click".

// 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 Bild-im-Bild-Fensters anpassen

Mit den Fenstermethoden resizeBy() und resizeTo() lässt sich die Größe des Bild-im-Bild-Fensters anpassen. Bei beiden Methoden ist eine Nutzergeste 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 öffnende Fenster verschieben

Verwenden Sie die Fenstermethode focus(), um das öffnende Fenster aus dem Bild-im-Bild-Fenster zu fokussieren. Für diese Methode ist eine Nutzergeste erforderlich.

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

CSS-Anzeigemodus „Bild im Bild“

Verwenden Sie den CSS-Anzeigemodus picture-in-picture, um spezifische CSS-Regeln zu schreiben, die nur angewendet werden, wenn die 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 VideoJS-Player-Demo der Document Picture-in-Picture API ausprobieren. Sehen Sie sich auf jeden Fall den Quellcode an.

Pomodoró

Tomodoro, eine Pomodoro-Webanwendung, nutzt ebenfalls die Document Picture-in-Picture API, sofern verfügbar (siehe GitHub-Pull-Anfrage).

Screenshot von Tomodoro, einer Pomodoro-Webanwendung.
Ein Bild-im-Bild-Fenster in Tomodoro.

Feedback

Bitte melden Sie Probleme auf GitHub mit Vorschlägen und Fragen.

Danksagungen

Hero-Image von Jakob Owens.