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

François Beaufort
François Beaufort

Unterstützte Browser

  • Chrome: 116.
  • Edge: 116.
  • Firefox: Nicht unterstützt.
  • Safari: Nicht unterstützt.

Quelle

Mit der Document Picture-in-Picture API können Sie ein Fenster öffnen, das immer im Vordergrund angezeigt wird und mit beliebigen HTML-Inhalten 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, mit einigen Unterschieden:

  • Das Bild-im-Bild-Fenster wird über anderen Fenstern angezeigt.
  • Das Bild-im-Bild-Fenster ist immer kleiner als das ursprüngliche Fenster.
  • 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. Erläuternde Mitteilung 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

Eine Website kann mit der vorhandenen Picture-in-Picture API für <video> ein Picture-in-Picture-Video anbieten. Die Funktion ist jedoch sehr eingeschränkt. Das vorhandene Bild-im-Bild-Fenster akzeptiert nur wenige Eingaben und bietet nur begrenzte Möglichkeiten zur Formatierung. Wenn ein vollständiges Dokument im Bild-im-Bild-Modus angezeigt wird, kann die Website benutzerdefinierte Steuerelemente und Eingaben bereitstellen (z. B. Untertitel, Playlists, Zeitachsen, „Mag ich“- und „Mag ich nicht“-Bewertungen), um die Bild-im-Bild-Videowiedergabe für Nutzer zu verbessern.

Videokonferenzsysteme

Es ist üblich, dass Nutzer während einer Videokonferenz den Browsertab aus verschiedenen Gründen verlassen (z. B. um einen anderen Tab für den Anruf zu präsentieren oder Multitasking zu betreiben), den Anruf aber trotzdem sehen möchten. Dies ist ein Haupteinsatzfall für „Bild im Bild“. Auch hier ist die aktuelle Funktionalität einer Videokonferenz-Website über die Picture-in-Picture API für <video> in Bezug auf Stil und Eingabemöglichkeiten eingeschränkt. Mit einem vollständigen Dokument im Bild-im-Bild-Modus können auf der Website mehrere Videostreams ganz einfach in einem einzigen PiP-Fenster kombiniert werden, ohne auf Canvas-Hacks zurückgreifen zu müssen. Außerdem können benutzerdefinierte Steuerelemente wie das Senden einer Nachricht, das Stummschalten eines anderen Nutzers oder das Heben der Hand bereitgestellt werden.

Produktivität

Studien haben gezeigt, dass Nutzer mehr Möglichkeiten benötigen, um im Web produktiv zu sein. Mit der Funktion „Dokument im Bild-im-Bild-Modus“ können Web-Apps flexibler genutzt werden. Egal, ob es um Textbearbeitung, Notizen, Aufgabenlisten, Messaging und Chat oder Design- und Entwicklungstools geht – Web-Apps können ihre Inhalte jetzt immer verfügbar machen.

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 Versprechen zurück, das aufgelöst wird, wenn ein Bild-im-Bild-Fenster geöffnet wird. Das Versprechen wird abgelehnt, wenn es ohne Nutzergeste aufgerufen wird. Das options-Wörterbuch enthält die folgenden optionalen Mitglieder:

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 diese Option aktiviert ist, wird die Schaltfläche „Zum Tab zurückkehren“ im Bild-im-Bild-Fenster ausgeblendet. Standardmäßig ist sie auf „False“ (Falsch) festgelegt.
preferInitialWindowPlacement
Wenn „wahr“ festgelegt ist, wird das Bild-im-Bild-Fenster an der Standardposition und in der Standardgröße geöffnet. Standardmäßig ist der Wert „falsch“.

Ereignisse

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

Beispiele

Im 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

Im folgenden JavaScript-Code 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 ein 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 du die Größe des Bild-im-Bild-Fensters festlegen möchtest, setze die Optionen width und height von documentPictureInPicture.requestWindow() auf die gewünschte Größe. Chrome kann die Optionswerte begrenzen, wenn sie zu groß oder zu klein sind, um in eine nutzerfreundliche 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 Bild-im-Bild-Fenster ausblenden

Wenn die Schaltfläche im Bild-im-Bild-Fenster, über die Nutzer zum Tab zurückkehren können, den Nutzer zum Tab zurückkehren können, ausgeblendet werden soll, setze die Option disallowReturnToOpener 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,
  });
});

Bild-im-Bild-Fenster an der Standardposition und in der Standardgröße öffnen

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

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

Wenn Sie alle CSS-Stylesheets aus dem ursprünglichen Fenster kopieren möchten, durchsuchen Sie die styleSheets, die explizit mit dem Dokument verknüpft oder darin eingebettet sind, und fügen Sie sie dem Bild-im-Bild-Fenster hinzu. Hinweis: Dies ist eine einmalige Kopie.

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

Wenn das Bild-im-Bild-Fenster geschlossen wird

Über das Fensterereignis "pagehide" können Sie feststellen, wann das Bild-im-Bild-Fenster geschlossen wird, entweder weil die Website dies veranlasst hat oder der Nutzer es manuell geschlossen hat. Im Event-Handler können Sie die Elemente wie hier gezeigt aus dem Bild-im-Bild-Fenster zurückholen.

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ße 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();

Hören, wenn die Website den Bild-im-Bild-Modus aktiviert

Über das "enter"-Ereignis auf documentPictureInPicture kannst du feststellen, wann ein Bild-im-Bild-Fenster geöffnet wird. Das Ereignis enthält ein window-Objekt, um auf das Bild-im-Bild-Fenster zuzugreifen.

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

Auf Elemente im Bild-im-Bild-Fenster zugreifen

Du kannst über das von documentPictureInPicture.requestWindow() zurückgegebene Objekt oder wie unten gezeigt über documentPictureInPicture.window auf Elemente im Bild-im-Bild-Fenster zugreifen.

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

Erstellen Sie Schaltflächen und Steuerelemente und reagieren Sie auf Nutzereingaben wie "click", 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 Bild-im-Bild-Fensters anpassen

Verwenden Sie die Fenstermethoden resizeBy() und resizeTo(), um die Größe des Bild-im-Bild-Fensters anzupassen. Für beide 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 Fenster legen, das geöffnet werden soll

Verwenden Sie die Fenstermethode focus(), um den Fokus im Bild-im-Bild-Fenster auf das Fenster zu legen, das geöffnet wurde. 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);

Bild-im-Bild-Modus von Preisvergleichsportalen

Verwenden Sie den CSS-Darstellungsmodus picture-in-picture, um bestimmte CSS-Regeln zu schreiben, die nur angewendet werden, wenn (ein Teil der) Webanwendung 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 für die Document Picture-in-Picture API ausprobieren. Sehen Sie sich auch den Quellcode an.

Pomodoro

Tomodoro, eine Pomodoro-Webanwendung, nutzt die Document Picture-in-Picture API, 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.