Signatur
Beschreibung
Das Ereignis enterpictureinpicture gehört zur Picture-in-Picture-API. Es wird am HTMLVideoElement ausgelöst, sobald das Video tatsächlich im schwebenden Bild-im-Bild-Fenster läuft. Dabei spielt es keine Rolle, ob der Wechsel per video.requestPictureInPicture() aus dem eigenen Code kam oder über die Bedienelemente des Browsers.
Das Ereignisobjekt ist ein PictureInPictureEvent. Seine Eigenschaft pictureInPictureWindow verweist auf das zugehörige PictureInPictureWindow. Darüber lassen sich die aktuelle Breite und Höhe (width, height) auslesen und mit dem Ereignis resize Größenänderungen des Fensters verfolgen, etwa um die Auflösung des Videostreams anzupassen.
Typische Einsätze sind: den Zustand der Oberfläche umschalten (z. B. einen Button von „Bild-im-Bild“ auf „Zurück zum Tab“ ändern), einen Platzhalter an der ursprünglichen Stelle des Videos anzeigen oder Analyse-Ereignisse erfassen. Als Gegenstück dient leavepictureinpicture. Den Handler kannst du mit addEventListener() registrieren oder über die Eigenschaft video.onenterpictureinpicture zuweisen.
Das Ereignis steigt im DOM auf (bubbles: true) und lässt sich nicht abbrechen. Du kannst den Moduswechsel damit also nicht verhindern, sondern nur darauf reagieren.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname, immer "enterpictureinpicture". |
|
| $handler Pflicht | (event: PictureInPictureEvent) => void | Callback-Funktion. Sie erhält ein PictureInPictureEvent mit der Eigenschaft pictureInPictureWindow. |
|
| $options | boolean | AddEventListenerOptions | false | Optionen wie once, passive, signal oder capture. |
Rückgabewert
addEventListener() gibt nichts zurück. Der Handler erhält ein PictureInPictureEvent.Beispiele
Oberfläche beim Wechsel in den Bild-im-Bild-Modus anpassen
const video = document.querySelector('#player');
const pipButton = document.querySelector('#pip-toggle');
pipButton.addEventListener('click', async () => {
try {
if (document.pictureInPictureElement === video) {
await document.exitPictureInPicture();
} else {
await video.requestPictureInPicture();
}
} catch (err) {
console.error('Bild-im-Bild fehlgeschlagen:', err.name);
}
});
video.addEventListener('enterpictureinpicture', (event) => {
pipButton.textContent = 'Zurück zum Tab';
video.classList.add('is-pip');
const { width, height } = event.pictureInPictureWindow;
console.log(`PiP-Fenster: ${width}×${height}`);
});
video.addEventListener('leavepictureinpicture', () => {
pipButton.textContent = 'Bild-im-Bild';
video.classList.remove('is-pip');
});
Größe des PiP-Fensters verfolgen
const video = document.querySelector('video');
const onResize = (e) => {
const { width, height } = e.target;
console.log(`Neue PiP-Größe: ${width}×${height}`);
};
video.addEventListener('enterpictureinpicture', (event) => {
const pipWindow = event.pictureInPictureWindow;
pipWindow.addEventListener('resize', onResize);
// Listener beim Verlassen wieder aufräumen
video.addEventListener('leavepictureinpicture', () => {
pipWindow.removeEventListener('resize', onResize);
}, { once: true });
});
Handler über die on-Property setzen und wieder entfernen
const video = document.querySelector('video');
video.onenterpictureinpicture = () => {
console.log('Video läuft jetzt im Bild-im-Bild-Fenster');
};
// Später: Handler entfernen
video.onenterpictureinpicture = null;
// Alternative mit addEventListener und AbortController
const controller = new AbortController();
video.addEventListener('enterpictureinpicture', () => {
console.log('PiP aktiv');
}, { signal: controller.signal });
controller.abort(); // entfernt den Listener
Funktionsprüfung vor der Registrierung
const video = document.querySelector('video');
const pipButton = document.querySelector('#pip-toggle');
const pipSupported = 'pictureInPictureEnabled' in document
&& document.pictureInPictureEnabled
&& !video.disablePictureInPicture;
if (pipSupported) {
video.addEventListener('enterpictureinpicture', () => {
console.log('PiP gestartet');
});
} else {
pipButton.hidden = true;
console.log('Bild-im-Bild wird nicht unterstützt');
}
// Wichtig · Fallstricke
- Browser-Unterstützung: Chromium-Browser (Chrome, Edge, Opera) und Safari unterstützen die API. Firefox hat zwar eine eigene Bild-im-Bild-Funktion, setzt aber die Picture-in-Picture-API nicht um. Dort wird dieses Ereignis nie ausgelöst. Prüfe die Unterstützung daher immer mit
document.pictureInPictureEnabled. requestPictureInPicture()braucht eine Nutzeraktion (transiente Aktivierung, z. B. einen Klick). Ohne sie wird das Promise mitNotAllowedErrorabgelehnt und keinenterpictureinpictureausgelöst.- Ist
video.disablePictureInPicturegesetzt, das Video noch nicht geladen (readyState === 0) oder hat es keine Videospur, schlägt der Wechsel fehl (InvalidStateError). - Es kann immer nur ein Element im Bild-im-Bild-Modus sein. Wechselt ein anderes Video hinein, erhält das vorherige zuerst
leavepictureinpicture. - Das Ereignis lässt sich nicht abbrechen.
preventDefault()hat keine Wirkung. - Die Picture-in-Picture-API für Videos ist nicht dasselbe wie die neuere Document Picture-in-Picture API (
documentPictureInPicture.requestWindow(), nur in Chromium). Diese löst andere Ereignisse aus. - Über die Permissions-Policy
picture-in-picturekann die Funktion in iframes gesperrt sein.