Start · Sprachen · JavaScript · Referenz · PictureInPictureEvent

PictureInPictureEvent

Schnittstelle

Ereignisobjekt für die Picture-in-Picture-Ereignisse <code>enterpictureinpicture</code> und <code>leavepictureinpicture</code> eines <code>&lt;video&gt;</code>-Elements, mit Zugriff auf das zugehörige PiP-Fenster.

seit JavaScript Chrome/Edge 70+, Safari 13.1+, Opera 57+; nicht in Kategorie: webapi

Signatur

interface PictureInPictureEvent extends Event

Beschreibung

PictureInPictureEvent ist Teil der Picture-in-Picture-API. Der Browser erzeugt dieses Ereignisobjekt, wenn ein HTMLVideoElement in den Bild-im-Bild-Modus wechselt (enterpictureinpicture) oder ihn wieder verlässt (leavepictureinpicture). Die Schnittstelle erbt alle Eigenschaften und Methoden von Event.

Die einzige zusätzliche Eigenschaft ist pictureInPictureWindow: Sie verweist auf das PictureInPictureWindow-Objekt, das das schwebende Fenster repräsentiert. Darüber lassen sich die aktuelle Fenstergröße (width, height) auslesen und ein resize-Listener registrieren – etwa um die Videoqualität an die Fenstergröße anzupassen oder Nutzungsstatistiken zu erfassen.

Typische Einsatzfälle sind das Umschalten eigener Bedienelemente (z. B. einen „PiP beenden“-Button anzeigen), das Ausblenden des Inline-Players, solange das Video im PiP-Fenster läuft, sowie das Anpassen der Stream-Auflösung. Die Ereignisse lassen sich sowohl per addEventListener() als auch über die Eigenschaften onenterpictureinpicture und onleavepictureinpicture des Video-Elements abonnieren.

Einen eigenen Konstruktor gibt es zwar (new PictureInPictureEvent(type, options)), er ist aber nur für synthetische Ereignisse sinnvoll, da pictureInPictureWindow Pflicht ist und ein PictureInPictureWindow nur vom Browser erzeugt werden kann.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Name des Ereignisses, z. B. "enterpictureinpicture" oder "leavepictureinpicture" (nur beim Konstruktor).
$options Pflicht PictureInPictureEventInit Initialisierungsobjekt. Enthält die Pflicht-Eigenschaft pictureInPictureWindow sowie optional die von EventInit geerbten Felder bubbles, cancelable und composed (jeweils Standard false).
$options.pictureInPictureWindow Pflicht PictureInPictureWindow Das PiP-Fenster, auf das sich das Ereignis bezieht. Später über event.pictureInPictureWindow lesbar (schreibgeschützt).

Beispiele

PiP starten und auf enterpictureinpicture reagieren

const video = document.querySelector('video');
const button = document.querySelector('#pip-button');

video.addEventListener('enterpictureinpicture', (event) => {
  const pipWindow = event.pictureInPictureWindow;
  console.log(`PiP aktiv: ${pipWindow.width}×${pipWindow.height}`);
  button.textContent = 'PiP beenden';

  // Größenänderungen des schwebenden Fensters verfolgen
  pipWindow.addEventListener('resize', () => {
    console.log(`Neue Größe: ${pipWindow.width}×${pipWindow.height}`);
  });
});

button.addEventListener('click', async () => {
  try {
    if (document.pictureInPictureElement) {
      await document.exitPictureInPicture();
    } else if (document.pictureInPictureEnabled) {
      await video.requestPictureInPicture();
    }
  } catch (err) {
    console.error('Picture-in-Picture fehlgeschlagen:', err);
  }
});
PiP aktiv: 400×225 Neue Größe: 560×315

leavepictureinpicture über die on-Property behandeln

const video = document.querySelector('video');
const button = document.querySelector('#pip-button');

video.onleavepictureinpicture = (event) => {
  console.log(event.type, event instanceof PictureInPictureEvent);
  button.textContent = 'Bild-im-Bild';
  // Video nach dem Schließen des PiP-Fensters pausieren
  video.pause();
};
leavepictureinpicture true

Listener wieder entfernen

const video = document.querySelector('video');

const onEnter = (event) => {
  console.log('PiP-Breite:', event.pictureInPictureWindow.width);
};

video.addEventListener('enterpictureinpicture', onEnter);

// Später, z. B. beim Abbau einer Komponente:
video.removeEventListener('enterpictureinpicture', onEnter);
// oder: video.onenterpictureinpicture = null;

Funktionsprüfung und synthetisches Ereignis

const video = document.querySelector('video');

if ('PictureInPictureEvent' in window) {
  video.addEventListener('enterpictureinpicture', async () => {
    // Ein vorhandenes PiP-Fenster wiederverwenden (nur für Tests sinnvoll)
    const pipWindow = await video.requestPictureInPicture().catch(() => null);
  }, { once: true });

  // Synthetisches Ereignis benötigt ein echtes PictureInPictureWindow:
  video.requestPictureInPicture().then((pipWindow) => {
    const testEvent = new PictureInPictureEvent('test-pip', {
      pictureInPictureWindow: pipWindow
    });
    console.log(testEvent.pictureInPictureWindow === pipWindow);
  });
} else {
  console.log('Picture-in-Picture-API wird nicht unterstützt');
}
true

// Wichtig · Fallstricke

  • Browser-Kompatibilität: Chromium-Browser (Chrome, Edge, Opera) und Safari ab 13.1 unterstützen die API. Firefox bietet zwar eine eigene PiP-Schaltfläche, implementiert die Web-API aber nicht – dort gibt es weder requestPictureInPicture() noch diese Ereignisse. Deshalb immer per document.pictureInPictureEnabled bzw. 'PictureInPictureEvent' in window prüfen.
  • Das resize-Ereignis wird am PictureInPictureWindow ausgelöst, nicht am Video-Element. Den Listener also über event.pictureInPictureWindow registrieren.
  • Nach leavepictureinpicture ist das Fenster geschlossen; width und height des alten PictureInPictureWindow liefern dann 0.
  • requestPictureInPicture() braucht eine Nutzeraktion (z. B. einen Klick), sonst wird das Promise mit NotAllowedError abgelehnt. Auch das Attribut disablepictureinpicture oder eine Permissions-Policy können PiP verhindern.
  • Die Ereignisse steigen standardmäßig im DOM auf (bubbles: true), lassen sich aber nicht abbrechen.
  • Nicht zu verwechseln mit der neueren Document Picture-in-Picture API (documentPictureInPicture), die beliebige HTML-Inhalte in einem PiP-Fenster anzeigt und das Ereignis DocumentPictureInPictureEvent verwendet.