Pantalla en pantalla para cualquier elemento, no solo para <video>

François Beaufort
François Beaufort

Navegadores compatibles

  • 116
  • 116
  • x
  • x

Origen

La API de Document Picture-in-Picture permite abrir una ventana siempre activa que se puede propagar con contenido HTML arbitrario. Extiende la API de Picture-in-Picture para <video> que solo permite que se coloque un elemento HTML <video> en una ventana Picture-in-Picture.

La ventana de pantalla en pantalla de la API de Pantalla en pantalla de documentos es similar a una ventana en blanco del mismo origen que se abre mediante window.open(), con algunas diferencias:

  • La ventana pantalla en pantalla flota sobre otras ventanas.
  • La ventana pantalla en pantalla nunca dura más que la ventana que se abre.
  • No es posible navegar por la ventana pantalla en pantalla.
  • El sitio web no puede establecer la posición de la ventana de pantalla en pantalla.
Una ventana pantalla en pantalla en la que se reproduce el video de avances de Sintel.
Ventana de pantalla en pantalla creada con la API de pantalla en pantalla del documento (demostración).

Estado actual

Step Estado
1. Crear explicación Completo
2. Crea el borrador inicial de la especificación En curso
3. Recopila comentarios e itera en el diseño En curso
4. Prueba de origen Completo
5. Lanzamiento Completo (computadora de escritorio)

Casos de uso

Reproductor de video personalizado

Un sitio web puede proporcionar una experiencia de video de pantalla en pantalla con la API de pantalla en pantalla de <video> existente. Sin embargo, esta es muy limitada. La ventana pantalla en pantalla existente acepta pocas entradas y tiene una capacidad limitada para asignarles un estilo. Con un documento en pantalla en pantalla completo, el sitio web puede proporcionar entradas y controles personalizados (por ejemplo, subtítulos, playlists, controles de arrastre de tiempo, marcar “me gusta” y “no me gusta” en los videos) para mejorar la experiencia del usuario en el modo de pantalla en pantalla.

Videoconferencias

Es común que los usuarios salgan de la pestaña del navegador durante una sesión de videoconferencia por varios motivos (por ejemplo, presentando otra pestaña en la llamada o realizando varias tareas a la vez) mientras aún desean ver la llamada, por lo que es uno de los principales casos de uso del modo pantalla en pantalla. Una vez más, la experiencia actual que un sitio web de videoconferencias puede ofrecer a través de la API de pantalla en pantalla para <video> es limitada en estilo y entrada. Con un documento completo en pantalla en pantalla, el sitio web puede combinar fácilmente varias transmisiones de video por Internet en una sola ventana de PIP sin depender de los hackeos de lienzo y proporcionar controles personalizados, como enviar un mensaje, silenciar a otro usuario o levantar la mano.

Productividad

Las investigaciones demostraron que los usuarios necesitan más formas de ser productivos en la Web. La función Documento en pantalla les brinda a las aplicaciones web la flexibilidad para lograr más tareas. Ya sea que necesites editar texto, tomar notas, crear listas de tareas, enviar mensajes y chatear, o utilizar herramientas de diseño y desarrollo, las aplicaciones web ahora pueden mantener siempre accesible el contenido.

Interfaz

Propiedades

documentPictureInPicture.window
Muestra la ventana de pantalla en pantalla actual, si existe. De lo contrario, muestra null.

Métodos

documentPictureInPicture.requestWindow(options)

Muestra una promesa que se resuelve cuando se abre una ventana de pantalla en pantalla. La promesa se rechaza si se la llama sin un gesto del usuario. El diccionario options contiene los siguientes miembros opcionales:

width
Establece el ancho inicial de la ventana pantalla en pantalla.
height
Establece la altura inicial de la ventana pantalla en pantalla.
disallowReturnToOpener
Oculta el botón “Volver a la pestaña” en la ventana Pantalla en pantalla si es verdadero. De forma predeterminada, es falso.

Eventos

documentPictureInPicture.onenter
Se activa el documentPictureInPicture cuando se abre una ventana de pantalla en pantalla.

Ejemplos

El siguiente código HTML configura un reproductor de video personalizado y un elemento de botón para abrir el reproductor de video en una ventana pantalla en pantalla.

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

Cómo abrir una ventana de pantalla en pantalla

El siguiente JavaScript llama a documentPictureInPicture.requestWindow() cuando el usuario hace clic en el botón para abrir una ventana en blanco de pantalla en pantalla. La promesa que se muestra se resuelve con un objeto JavaScript de ventana Picture-in-Picture. El reproductor de video se mueve a esa ventana con 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);
});

Establece el tamaño de la ventana Pantalla en pantalla

Para establecer el tamaño de la ventana pantalla en pantalla, establece las opciones width y height de documentPictureInPicture.requestWindow() en el tamaño deseado de la ventana pantalla en pantalla. Es posible que Chrome restrinja los valores de las opciones si son demasiado grandes o demasiado pequeños para adaptarse a un tamaño de ventana fácil de usar.

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

Ocultar el botón "volver a la pestaña" de la ventana Pantalla en pantalla

Para ocultar el botón en la ventana Pantalla en pantalla que le permite al usuario volver a la pestaña de apertura, establece la opción disallowReturnToOpener de documentPictureInPicture.requestWindow() en 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,
  });
});

Copiar hojas de estilo en la ventana Pantalla en pantalla

Para copiar todas las hojas de estilo CSS de la ventana de origen, realiza un bucle a través de styleSheets explícitamente vinculado o incrustado en el documento y agrégalos a la ventana pantalla en pantalla. Ten en cuenta que esta copia es única.

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

Controla el cierre de la ventana Pantalla en pantalla

Escucha el evento "pagehide" de la ventana para saber cuándo se cierra la ventana de pantalla en pantalla (ya sea porque la inició el sitio web o el usuario la cerró manualmente). El controlador de eventos es un buen lugar para recuperar los elementos de la ventana Picture-in-Picture, como se muestra a continuación.

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

Cierra la ventana pantalla en pantalla de manera programática con el método close().

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

Escuchar cuando el sitio web ingresa al modo de pantalla en pantalla

Escucha el evento "enter" en documentPictureInPicture para saber cuándo se abre una ventana de pantalla en pantalla. El evento contiene un objeto window para acceder a la ventana pantalla en pantalla.

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

Accede a los elementos en la ventana Pantalla en pantalla

Accede a los elementos de la ventana Picture-in-Picture desde el objeto que muestra documentPictureInPicture.requestWindow() o con documentPictureInPicture.window, como se muestra a continuación.

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

Controla eventos desde la ventana pantalla en pantalla

Crea botones y controles, y responde a los eventos de entrada del usuario, como "click", como lo harías normalmente 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);

Cómo cambiar el tamaño de la ventana Pantalla en pantalla

Usa los métodos de ventana resizeBy() y resizeTo() para cambiar el tamaño de la ventana pantalla en pantalla. Ambos métodos requieren un gesto del usuario.

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

Enfocar la ventana del dispositivo de apertura

Usa el método de ventana focus() para enfocar la ventana de apertura desde la ventana pantalla en pantalla. Este método requiere un gesto del usuario.

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

Modo de visualización de pantalla en pantalla de CSS

Usa el modo de visualización picture-in-picture de CSS para escribir reglas de CSS específicas que solo se aplican cuando la app web se muestra en el modo de pantalla en pantalla (parte de ella).

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

Detección de funciones

Para verificar si se admite la API de Document Picture-in-Picture, usa lo siguiente:

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

Demostraciones

Reproductor de VideoJS

Puedes jugar con la demostración del reproductor VideoJS de la API de Document Picture-in-Picture. Asegúrate de consultar el código fuente.

Pomodoro

Tomodoro, una app web de pomodoro, también aprovecha la API de pantalla en pantalla de documentos, cuando está disponible (consulta la solicitud de extracción de GitHub).

Captura de pantalla de Tomodoro, una aplicación web de pomodoro.
Ventana de pantalla en pantalla en Tomodoro

Comentarios

Informa los problemas en GitHub con sugerencias y preguntas.

Agradecimientos

Hero image de Jakob Owens.