Picture-in-picture pour tous les éléments, pas uniquement les <vidéos>

François Beaufort
François Beaufort

Navigateurs pris en charge

  • Chrome: 116 <ph type="x-smartling-placeholder">
  • Edge: 116 <ph type="x-smartling-placeholder">
  • Firefox: non compatible. <ph type="x-smartling-placeholder">
  • Safari: non compatible. <ph type="x-smartling-placeholder">

Source

L'API Document Picture-in-picture permet d'ouvrir une fenêtre toujours affichée au-dessus, qui peut être remplie avec du contenu HTML arbitraire. Il étend l'API Picture-in-picture pour <video> existante, qui permet uniquement d'insérer un élément <video> HTML dans une fenêtre Picture-in-picture.

La fenêtre Picture-in-picture de l'API Document Picture-in-picture est semblable à une fenêtre vide de même origine ouverte via window.open(), à quelques différences près:

  • La fenêtre Picture-in-picture flotte au-dessus des autres fenêtres.
  • La fenêtre Picture-in-picture ne survit jamais à la fenêtre qui s'ouvre.
  • Impossible de naviguer dans la fenêtre Picture-in-picture.
  • Le site Web ne peut pas définir la position de la fenêtre Picture-in-picture.
<ph type="x-smartling-placeholder">
</ph> Fenêtre Picture-in-picture affichant la bande-annonce de Sintel.
Fenêtre Picture-in-picture créée avec l'API Document Picture-in-picture (démonstration).

État actuel

Étape État
1. Créer une vidéo explicative Fin
2. Créer l'ébauche initiale de la spécification En cours
3. Recueillir des commentaires et itérer sur la conception En cours
4. Phase d'évaluation Fin
5. Lancement Terminée (ordinateur)

Cas d'utilisation

Lecteur vidéo personnalisé

Un site Web peut fournir une expérience vidéo Picture-in-picture avec l'API Picture-in-picture pour <video> existante, mais elle est très limitée. La fenêtre Picture-in-picture existante accepte peu d'entrées et dispose d'une capacité limitée pour leur appliquer un style. Avec un document complet en Picture-in-picture, le site Web peut fournir des commandes et des entrées personnalisées (par exemple, des sous-titres, des playlists, une barre de lecture, des mentions "J'aime" et "Je n'aime pas" pour les vidéos) afin d'améliorer l'expérience utilisateur en mode Picture-in-picture.

Visioconférence

Les utilisateurs quittent souvent l'onglet du navigateur pendant une visioconférence pour diverses raisons (par exemple, pour présenter un autre onglet lors de l'appel ou effectuer plusieurs tâches à la fois) tout en souhaitant toujours voir l'appel. Il s'agit donc d'un cas d'utilisation de premier choix pour le Picture-in-picture. Là encore, le style et les possibilités d'entrée pour un site Web de visioconférence via l'API Picture-in-picture pour <video> sont limités. Grâce au mode Document complet en Picture-in-picture, le site Web peut facilement combiner plusieurs flux vidéo dans une même fenêtre PIP sans avoir à recourir au piratage du canevas. Il offre en outre des commandes personnalisées telles que l'envoi d'un message, le masquage d'un autre utilisateur ou la possibilité de lever la main.

Productivité

Des études ont montré que les utilisateurs ont besoin de moyens supplémentaires pour être productifs sur le Web. La fonctionnalité Document en Picture-in-picture donne aux applications Web la flexibilité d'en faire plus. Que ce soit pour modifier du texte, prendre des notes, créer des listes de tâches, envoyer des messages et discuter, ou utiliser des outils de conception et de développement, les applications Web offrent désormais un contenu toujours accessible.

Interface

Propriétés

documentPictureInPicture.window
Renvoie la fenêtre Picture-in-picture actuelle, le cas échéant. Sinon, renvoie null.

Méthodes

documentPictureInPicture.requestWindow(options)

Affiche une promesse qui se résout lorsqu'une fenêtre Picture-in-picture est ouverte. La promesse est refusée si elle est appelée sans geste de l'utilisateur. Le dictionnaire options contient les membres facultatifs suivants:

width
Définit la largeur initiale de la fenêtre Picture-in-picture.
height
Définit la hauteur initiale de la fenêtre Picture-in-picture.
disallowReturnToOpener
Masquer le bouton "Retour à l'onglet" de la fenêtre Picture-in-picture si "true". La valeur par défaut est "false".

Événements

documentPictureInPicture.onenter
Déclenchement sur documentPictureInPicture lors de l'ouverture d'une fenêtre Picture-in-picture.

Exemples

Le code HTML suivant configure un lecteur vidéo personnalisé et un élément de bouton pour ouvrir le lecteur vidéo dans une fenêtre Picture-in-picture.

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

Ouvrir une fenêtre Picture-in-picture

Le code JavaScript suivant appelle documentPictureInPicture.requestWindow() lorsque l'utilisateur clique sur le bouton pour ouvrir une fenêtre Picture-in-picture vide. La promesse renvoyée est résolue avec un objet JavaScript de fenêtre Picture-in-picture. Le lecteur vidéo est déplacé vers cette fenêtre avec 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);
});

Définir la taille de la fenêtre Picture-in-picture

Pour définir la taille de la fenêtre Picture-in-picture, définissez les options width et height de documentPictureInPicture.requestWindow() sur la taille de fenêtre Picture-in-picture souhaitée. Chrome peut limiter les valeurs d'option si elles sont trop grandes ou trop petites pour s'adapter à une taille de fenêtre conviviale.

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

Masquer le bouton "Retour à l'onglet" bouton de la fenêtre Picture-in-picture

Pour masquer le bouton permettant à l'utilisateur de revenir à l'onglet d'ouverture dans la fenêtre Picture-in-picture, définissez l'option disallowReturnToOpener de documentPictureInPicture.requestWindow() sur 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,
  });
});

Copier des feuilles de style dans la fenêtre Picture-in-picture

Pour copier toutes les feuilles de style CSS depuis la fenêtre d'origine, faites une boucle dans les styleSheets explicitement liées au document ou intégrées dans celui-ci, puis ajoutez-les à la fenêtre Picture-in-picture. Notez qu'il s'agit d'une copie unique.

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

Gérer la fermeture de la fenêtre Picture-in-picture

Écoutez l'événement "pagehide" de la fenêtre pour savoir quand la fenêtre Picture-in-picture est fermée (par le site Web qui l'a lancée ou par l'utilisateur la fermée manuellement). Le gestionnaire d'événements est idéal pour extraire les éléments de la fenêtre Picture-in-picture, comme illustré ci-dessous.

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

Fermez la fenêtre Picture-in-picture par programmation à l'aide de la méthode close().

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

Écouter lorsque le site Web passe en mode Picture-in-picture

Écoutez l'événement "enter" sur documentPictureInPicture pour savoir quand une fenêtre Picture-in-picture est ouverte. L'événement contient un objet window permettant d'accéder à la fenêtre Picture-in-picture.

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

Accéder aux éléments de la fenêtre Picture-in-picture

Accédez aux éléments de la fenêtre Picture-in-picture à partir de l'objet renvoyé par documentPictureInPicture.requestWindow() ou avec documentPictureInPicture.window, comme indiqué ci-dessous.

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

Gérer les événements de la fenêtre Picture-in-picture

Créez des boutons et des commandes, et répondez aux événements d'entrée de l'utilisateur tels que "click" comme vous le feriez normalement en 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);

Redimensionner la fenêtre Picture-in-picture

Utilisez les méthodes resizeBy() et resizeTo() pour redimensionner la fenêtre Picture-in-picture. Les deux méthodes nécessitent un geste de l'utilisateur.

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

Sélectionner la fenêtre d'ouverture

Utilisez la méthode Fenêtre focus() pour sélectionner la fenêtre d'ouverture à partir de la fenêtre Picture-in-picture. Cette méthode nécessite un geste de l'utilisateur.

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

Mode d'affichage Picture-in-picture CSS

Utilisez le mode d'affichage CSS picture-in-picture pour écrire des règles CSS spécifiques qui ne s'appliquent que lorsque (en partie) l'application Web est affichée en mode Picture-in-picture.

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

Détection de caractéristiques

Pour vérifier si l'API Document Picture-in-picture est compatible, utilisez:

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

Démonstrations

Lecteur VideoJS

Vous pouvez utiliser la démo du lecteur VideoJS de l'API Document Picture-in-picture. Pensez à consulter le code source.

Pomodoro

Tomodoro, une application Web pomodoro, tire également parti de l'API Document Picture-in-picture lorsqu'elle est disponible (voir la page Demande d'extraction GitHub).

<ph type="x-smartling-placeholder">
</ph> Capture d&#39;écran de Tomodoro, une application Web Pomodoro
Une fenêtre Picture-in-picture dans Tomodoro.

Commentaires

Veuillez signaler les problèmes sur GitHub en envoyant vos suggestions et vos questions.

Remerciements

Image principale par Jakob Owens.