Picture-in-Picture voor elk element, niet alleen <video>

François Beaufort
François Beaufort

Browser Support

  • Chrome: 116.
  • Rand: 116.
  • Firefox Technology Preview: ondersteund.
  • Safari: niet ondersteund.

Source

De Document Picture-in-Picture API maakt het mogelijk om een ​​venster te openen dat altijd bovenaan blijft staan ​​en dat gevuld kan worden met willekeurige HTML-inhoud. Het is een uitbreiding van de bestaande Picture-in-Picture API voor <video> , die alleen toestaat dat een HTML <video> -element in een Picture-in-Picture (PiP)-venster wordt geplaatst.

Het Picture-in-Picture-venster in de Document Picture-in-Picture API is vergelijkbaar met een leeg venster van dezelfde oorsprong dat wordt geopend met window.open() , met enkele verschillen:

  • Het Picture-in-Picture-venster zweeft boven andere vensters.
  • Het beeld-in-beeldvenster blijft altijd intact, zelfs als het venster zelf open kan.
  • Het Picture-in-Picture-venster kan niet worden bediend.
  • De positie van het Picture-in-Picture-venster kan niet door de website worden ingesteld.
Een Picture-in-Picture-venster waarin de trailer van Sintel wordt afgespeeld.
Een Picture-in-Picture-venster gemaakt met de Document Picture-in-Picture API ( demo ).

Status

Stap Status
1. Maak een uitleg Compleet
2. Stel een eerste concept van de specificatie op. In behandeling
3. Verzamel feedback en pas het ontwerp aan In behandeling
4. Oorsprongsproef Compleet
5. Lancering Compleet (Desktop)

Gebruiksvoorbeelden

Je kunt deze API op verschillende manieren gebruiken, bijvoorbeeld voor aangepaste videospelers, videoconferenties en productiviteitsapps.

Aangepaste videospeler

Een website kan een Picture-in-Picture-video-ervaring bieden met de bestaande Picture-in-Picture API voor <video> , maar dit is zeer beperkt. Het bestaande PiP-venster accepteert weinig invoer en biedt beperkte mogelijkheden voor styling. Met een volledig document in Picture-in-Picture-modus kan de website aangepaste bedieningselementen en invoeropties bieden (bijvoorbeeld ondertiteling , afspeellijsten, een tijdsschuifregelaar, de mogelijkheid om video's te liken en te disliken) om de PiP-video-ervaring van de gebruiker te verbeteren.

Videoconferenties

Gebruikers verlaten vaak tijdelijk het browsertabblad tijdens een videoconferentie, bijvoorbeeld om vanuit een ander tabblad te presenteren, aantekeningen te maken of andere multitasking-activiteiten uit te voeren. In de meeste gevallen wil de gebruiker echter wel het gesprek blijven volgen, waardoor dit een ideale toepassing is voor Picture-in-Picture. De huidige mogelijkheden van een videoconferentiewebsite met de Picture-in-Picture API voor <video> zijn echter beperkt qua stijl en invoermogelijkheden. Met een volledig document in Picture-in-Picture kan de website eenvoudig meerdere videostreams combineren in één PiP-venster, zonder gebruik te hoeven maken van canvas-trucs , en aangepaste bedieningselementen bieden, zoals het versturen van een bericht, het dempen van een andere gebruiker of het opsteken van een hand.

Productiviteit

Onderzoek heeft aangetoond dat gebruikers meer mogelijkheden nodig hebben om productief te zijn op het web. Documenten in Picture-in-Picture geven webapps de flexibiliteit om meer te bereiken. Of het nu gaat om tekstbewerking, notities maken, takenlijsten, berichten en chatten, of ontwerp- en ontwikkeltools, webapps kunnen hun content nu altijd toegankelijk houden.

Interface

Eigenschappen

documentPictureInPicture.window
Geeft het huidige Picture-in-Picture-venster terug, indien aanwezig. Anders wordt null geretourneerd.

Methoden

documentPictureInPicture.requestWindow(options)

Retourneert een promise die wordt opgelost wanneer een Picture-in-Picture-venster wordt geopend. De promise wordt afgewezen als deze wordt aangeroepen zonder een gebruikersactie. Het options bevat de volgende optionele leden:

width
Hiermee wordt de beginbreedte van het Picture-in-Picture-venster ingesteld.
height
Hiermee wordt de beginhoogte van het Picture-in-Picture-venster ingesteld.
disallowReturnToOpener
Verbergt de knop "Terug naar tabblad" in het Picture-in-Picture-venster als deze is ingeschakeld. Standaard is deze uitgeschakeld.
preferInitialWindowPlacement
Als deze optie is ingeschakeld, wordt het Picture-in-Picture-venster op de standaardpositie en -grootte geopend. Standaard is deze optie uitgeschakeld.

Evenementen

documentPictureInPicture.onenter
Wordt geactiveerd bij documentPictureInPicture wanneer een Picture-in-Picture-venster wordt geopend.

Voorbeelden

De volgende HTML-code configureert een aangepaste videospeler en een knop om de videospeler in een Picture-in-Picture-venster te openen.

<div id="playerContainer">
  <div id="player">
    <video id="video"></video>
  </div>
</div>
<button id="pipButton">Open Picture-in-Picture window</button>

Open een Picture-in-Picture-venster

De volgende JavaScript-code roept documentPictureInPicture.requestWindow() aan wanneer de gebruiker op de knop klikt om een ​​leeg Picture-in-Picture-venster te openen. De geretourneerde promise wordt opgelost met een JavaScript-object voor het Picture-in-Picture-venster. De videospeler wordt naar dat venster verplaatst met behulp van append() .

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

Stel de grootte van het Picture-in-Picture-venster in.

Om de grootte van het Picture-in-Picture-venster in te stellen, stelt u de width en height van documentPictureInPicture.requestWindow() in op de gewenste PiP-venstergrootte. Chrome kan de optiewaarden verkleinen als ze te groot of te klein zijn voor een gebruiksvriendelijke venstergrootte.

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

Verberg de knop "terug naar tabblad" in het PiP-venster.

Om de knop in het Picture-in-Picture-venster te verbergen waarmee de gebruiker terug kan gaan naar het geopende tabblad, stelt u de optie disallowReturnToOpener van documentPictureInPicture.requestWindow() in op 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,
  });
});

Open PiP naar de standaardpositie en -grootte.

Om de positie of grootte van het vorige Picture-in-Picture-venster niet opnieuw te gebruiken, stelt u de optie preferInitialWindowPlacement van documentPictureInPicture.requestWindow() in op true .

pipButton.addEventListener("click", async () => {
  // Open a Picture-in-Picture window in its default position / size.
  const pipWindow = await documentPictureInPicture.requestWindow({
    preferInitialWindowPlacement: true,
  });
});

Kopieer stijlbladen naar PiP

Om alle CSS-stijlbladen van het oorspronkelijke venster te kopiëren, doorloop je styleSheets die expliciet in het document zijn gekoppeld of ingesloten en voeg je ze toe aan het Picture-in-Picture-venster. Houd er rekening mee dat dit een eenmalige kopie is.

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

Afhandeling wanneer het PiP-venster sluit

Luister naar de "pagehide" -gebeurtenis van het venster om te weten wanneer het Picture-in-Picture-venster wordt gesloten (hetzij door de website, hetzij door de gebruiker zelf). De gebeurtenishandler is een goede plek om de elementen weer uit het Picture-in-Picture-venster te halen, zoals hier wordt getoond.

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

Sluit het Picture-in-Picture-venster programmatisch met behulp van de close() methode.

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

Luister wanneer de website overgaat naar PiP (Picture-in-Picture).

Luister naar de "enter" -gebeurtenis op documentPictureInPicture om te weten wanneer een Picture-in-Picture-venster wordt geopend. De gebeurtenis bevat een window waarmee toegang tot het Picture-in-Picture-venster kan worden verkregen.

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

Toegang tot elementen in het PiP-venster

Je hebt toegang tot elementen in het Picture-in-Picture-venster via het object dat wordt geretourneerd door documentPictureInPicture.requestWindow() , of met documentPictureInPicture.window .

const pipWindow = documentPictureInPicture.window;
if (pipWindow) {
  // Mute video playing in the Picture-in-Picture window.
  const pipVideo = pipWindow.document.querySelector("#video");
  pipVideo.muted = true;
}

Verwerk gebeurtenissen vanuit het PiP-venster.

Maak knoppen en besturingselementen aan en reageer op invoergebeurtenissen van de gebruiker (zoals "click" ), zoals altijd in JavaScript.

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

Verklein of vergroot het PiP-venster

Gebruik de Window-methoden resizeBy() en resizeTo() om het Picture-in-Picture-venster te vergroten of verkleinen. Beide methoden vereisen een gebruikersactie.

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

Focus het openingsvenster

Gebruik de focus() `-methode van het venster om het geopende venster te focussen vanuit het Picture-in-Picture-venster. Deze methode vereist een gebruikersactie.

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

CSS PiP-weergavemodus

Gebruik de CSS-weergavemodus picture-in-picture om specifieke CSS-regels te schrijven die alleen worden toegepast wanneer (een deel van) de webapplicatie in de 'picture-in-picture'-modus wordt weergegeven.

@media all and (display-mode: picture-in-picture) {
  body {
    margin: 0;
  }
  h1 {
    font-size: 0.8em;
  }
}

Kenmerkdetectie

Om te controleren of de Document Picture-in-Picture API wordt ondersteund, gebruikt u:

if ('documentPictureInPicture' in window) {
  // The Document Picture-in-Picture API is supported.
}

Demo's

Tomodoro, een webapplicatie voor de Pomodoro-techniek.
Een Picture-in-Picture-venster in Tomodoro.

Deel je feedback

Meld problemen op GitHub met suggesties en vragen.