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

François Beaufort
François Beaufort

Unterstützte Browser

  • Chrome: 116. <ph type="x-smartling-placeholder">
  • Edge: 116. <ph type="x-smartling-placeholder">
  • Firefox: nicht unterstützt <ph type="x-smartling-placeholder">
  • Safari: nicht unterstützt. <ph type="x-smartling-placeholder">

Quelle

Mit der Document Picture-in-Picture API lässt sich ein Always-on-Top-Fenster öffnen, das 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 Ursprungsfenster, das über window.open() geöffnet wurde, mit einigen Unterschieden:

  • Das Bild-im-Bild-Fenster schwebt über anderen Fenstern.
  • Das Bild-im-Bild-Fenster überdauert niemals das sich öffnende Fenster.
  • Die Navigation im Bild-im-Bild-Fenster ist nicht möglich.
  • Die Position des Bild-im-Bild-Fensters kann nicht von der Website festgelegt werden.
<ph type="x-smartling-placeholder">
</ph> Ein Bild-im-Bild-Fenster, das Sintel-Trailervideo abspielt.
Ein Bild-im-Bild-Fenster, das mit der Document Picture-in-Picture API erstellt wurde (Demo).

Aktueller Status

Schritt Status
1. Erklärende 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. Einführung Abgeschlossen (Computer)

Anwendungsfälle

Benutzerdefinierter Videoplayer

Eine Website kann mit der vorhandenen Picture-in-Picture-API für <video> Bild-im-Bild-Videos anbieten, dies ist jedoch sehr begrenzt. Für das bestehende Bild-im-Bild-Fenster sind nur wenige Eingaben möglich und die Gestaltungsmöglichkeiten sind eingeschränkt. Mit einem vollständigen Dokument im Bild-im-Bild-Format kann die Website benutzerdefinierte Steuerelemente und Eingaben anbieten (z. B. Untertitel, Playlists, Zeit-Scrubber sowie Videos mit „Mag ich“- und „Mag ich nicht“-Bewertungen), um die Bild-im-Bild-Funktion der Nutzer zu verbessern.

Videokonferenzsysteme

Nutzer verlassen den Browsertab während einer Videokonferenz oft aus verschiedenen Gründen, z. B. weil sie einen anderen Tab während des Anrufs einblenden möchten, aber trotzdem den Anruf nicht sehen möchten. Daher eignet sich die Funktion besonders gut für die Funktion „Bild im Bild“. Wie bereits erwähnt, sind die Möglichkeiten, die eine Videokonferenz-Website über die Picture-in-Picture API für <video> derzeit bieten kann, hinsichtlich Design und Eingabe begrenzt. Mit einem vollständigen Dokument im Bild-im-Bild-Modus kann die Website ganz einfach mehrere Videostreams zu einem einzigen BiB-Fenster kombinieren, ohne Canvas-Hacks nutzen zu müssen. Außerdem bietet sie benutzerdefinierte Steuerelemente wie das Senden einer Nachricht, das Stummschalten eines anderen Nutzers oder das Melden.

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“ können Web-Apps noch mehr erreichen. Ob Textbearbeitung, Notizen, Aufgabenlisten, Messaging und Chat oder Design- und Entwicklungstools – Web-Apps sorgen jetzt dafür, dass immer auf ihre Inhalte zugegriffen werden kann.

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 eine Nutzergeste aufgerufen wird. Das Wörterbuch options 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
Blendet „Zurück zum Tab“ aus im Bild-im-Bild-Fenster, wenn dies auf „true“ gesetzt ist. Der Standardwert ist „false“.

Ereignisse

documentPictureInPicture.onenter
Wird ausgelöst am documentPictureInPicture, 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

Der folgende JavaScript-Code ruft documentPictureInPicture.requestWindow() auf, wenn der Nutzer auf die Schaltfläche klickt, um ein leeres Bild-im-Bild-Fenster zu öffnen. Das zurückgegebene Promise wird mit einem Bild-im-Bild-Fenster-JavaScript-Objekt aufgelöst. Der Videoplayer wird über 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, setze die Optionen width und height von documentPictureInPicture.requestWindow() auf die gewünschte Größe des Bild-im-Bild-Fensters. Chrome schränkt die Optionswerte möglicherweise ein, 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);
});

„Zurück zum Tab“ ausblenden des Bild-im-Bild-Fensters

Um die Schaltfläche im Bild-im-Bild-Fenster auszublenden, über die der Nutzer zum Öffnenden-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, das explizit im Dokument verlinkt oder eingebettet ist, und hängen Sie sie an das Bild-im-Bild-Fenster an. 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);
});

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

Hören Sie sich das Ereignis "pagehide" des Fensters an, um zu erfahren, wann das Bild-im-Bild-Fenster geschlossen wird (entweder weil es von der Website initiiert oder vom Nutzer manuell geschlossen wurde). Der Event-Handler ist ein guter Ort, um die Elemente wie unten gezeigt wieder aus dem Bild-im-Bild-Fenster zu verschieben.

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

Mit der Methode close() kannst du das Bild-im-Bild-Fenster programmatisch schließen.

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

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

Hören Sie sich das "enter"-Ereignis auf documentPictureInPicture an, 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

Auf Elemente im Bild-im-Bild-Fenster kann entweder über das von documentPictureInPicture.requestWindow() zurückgegebene Objekt oder über documentPictureInPicture.window (siehe unten) zugegriffen werden.

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 Eingaben von Nutzern 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 ändern

Mit den Fenstermethoden resizeBy() und resizeTo() können Sie die Größe des Bild-im-Bild-Fensters anpassen. Beide Methoden erfordern eine Nutzergeste.

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

Öffnendes Fenster fokussieren

Verwenden Sie die Fenstermethode focus(), um das Öffnungsfenster des Bild-im-Bild-Fensters 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-Bild-im-Bild-Anzeigemodus

Mit dem CSS-Anzeigemodus picture-in-picture kannst du bestimmte CSS-Regeln schreiben, die nur angewendet werden, wenn die Webanwendung (Teil der) 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

JS-Videoplayer

Sie können die VideoJS-Player-Demo der Document Picture-in-Picture API ausprobieren. Sehen Sie sich unbedingt den Quellcode an.

Pomodoro

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

<ph type="x-smartling-placeholder">
</ph> Screenshot von Tomodoro, einer Pomodoro-Webanwendung.
Ein Bild-im-Bild-Fenster in Tomodoro

Feedback

Bitte melde Probleme auf GitHub mit Vorschlägen und Fragen.

Danksagungen

Hero-Image von Jakob Owens.