A API Document Picture-in-Picture permite abrir uma janela sempre ativa que pode ser preenchida com conteúdo HTML arbitrário. Ela estende a API Picture-in-Picture para <video>, que só permite que um elemento <video> HTML seja colocado em uma janela picture-in-picture (PiP).
A janela picture-in-picture na API Document Picture-in-Picture é semelhante
a uma janela em branco da mesma origem aberta usando window.open(), com algumas diferenças:
- A janela picture-in-picture flutua sobre outras janelas.
- A janela picture-in-picture nunca sobrevive à janela de abertura.
- Não é possível navegar na janela picture-in-picture.
- A posição da janela picture-in-picture não pode ser definida pelo site.
Status
| Etapa | Status |
|---|---|
| 1. Criar explicação | Concluído |
| 2. Criar rascunho inicial da especificação | Em andamento |
| 3. Coletar feedback e iterar no design | Em andamento |
| 4. Teste de origem | Concluído |
| 5. Abra o | Concluído (computador) |
Casos de uso
Você pode usar essa API de várias maneiras, incluindo players de vídeo personalizados, videoconferências e apps de produtividade.
Player de vídeo personalizado
Um site pode oferecer uma experiência de vídeo picture-in-picture com a API Picture-in-Picture para <video>, mas ela é muito limitada. A janela PiP aceita poucas entradas e tem capacidade limitada para estilização. Com um documento completo no modo picture-in-picture, o site pode fornecer controles e entradas personalizados (por exemplo, legendas, playlists, barra de progressão, curtidas e não curtidas de vídeos) para melhorar a experiência de vídeo PiP do usuário.
Videoconferências
Os usuários costumam sair temporariamente da guia do navegador durante uma sessão de videoconferência, por exemplo, ao apresentar de outra guia para a chamada, fazer anotações ou outras atividades multitarefa. No entanto, na maioria dos casos, o usuário ainda quer ver a chamada. Portanto, esse é um caso de uso ideal para o modo picture-in-picture. Mais uma vez, a experiência atual que um site de videoconferência pode oferecer com a API Picture-in-Picture para <video> é limitada em estilo e entrada. Com um documento completo no modo picture-in-picture, o site pode combinar facilmente vários streams de vídeo em uma única janela PiP, sem depender de hacks de tela, e fornecer controles personalizados, como enviar uma mensagem, silenciar outro usuário ou levantar a mão.
Produtividade
Pesquisas mostraram que os usuários precisam de mais maneiras de serem produtivos na Web. O documento no modo picture-in-picture oferece aos apps da Web a flexibilidade de realizar mais tarefas. Sejam ferramentas de edição de texto, anotações, listas de tarefas, mensagens e chat ou design e desenvolvimento, os apps da Web agora podem manter o conteúdo sempre acessível.
Interface
Propriedades
documentPictureInPicture.window- Retorna a janela picture-in-picture atual, se houver. Caso contrário, retorna
null.
Métodos
documentPictureInPicture.requestWindow(options)Retorna uma promessa que é resolvida quando uma janela picture-in-picture é aberta. A promessa é rejeitada se for chamada sem um gesto do usuário. O dicionário
optionscontém os seguintes membros opcionais:width- Define a largura inicial da janela picture-in-picture.
height- Define a altura inicial da janela picture-in-picture.
disallowReturnToOpener- Oculta o botão "Voltar à guia" na janela picture-in-picture se for verdadeiro. O padrão é "false".
preferInitialWindowPlacement- Abre a janela picture-in-picture na posição e no tamanho padrão se for verdadeiro. O padrão é "false".
Eventos
documentPictureInPicture.onenter- Acionado em
documentPictureInPicturequando uma janela picture-in-picture é aberta.
Exemplos
O HTML a seguir configura um player de vídeo personalizado e um elemento de botão para abrir o player de vídeo em uma janela picture-in-picture.
<div id="playerContainer">
<div id="player">
<video id="video"></video>
</div>
</div>
<button id="pipButton">Open Picture-in-Picture window</button>
Abrir uma janela picture-in-picture
O JavaScript a seguir chama documentPictureInPicture.requestWindow() quando o usuário clica no botão para abrir uma janela picture-in-picture em branco. A promessa retornada é resolvida com um objeto JavaScript de janela picture-in-picture. O player de vídeo é movido para essa janela usando 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);
});
Definir o tamanho da janela picture-in-picture
Para definir o tamanho da janela picture-in-picture, defina as opções width e height de documentPictureInPicture.requestWindow() para o tamanho ideal da janela PiP. O Chrome pode reduzir os valores da opção se eles forem muito grandes ou muito pequenos para caber em um tamanho de janela 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 o botão "Voltar à guia" na janela PiP
Para ocultar o botão na janela picture-in-picture que permite ao usuário voltar à guia de abertura, defina a opção disallowReturnToOpener de documentPictureInPicture.requestWindow() como 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,
});
});
Abrir o PiP na posição e no tamanho padrão
Para não reutilizar a posição ou o tamanho da janela picture-in-picture anterior, defina a opção preferInitialWindowPlacement de documentPictureInPicture.requestWindow() como true.
pipButton.addEventListener("click", async () => {
// Open a Picture-in-Picture window in its default position / size.
const pipWindow = await documentPictureInPicture.requestWindow({
preferInitialWindowPlacement: true,
});
});
Copiar folhas de estilo para o PiP
Para copiar todas as folhas de estilo CSS da janela de origem, faça um loop em styleSheets explicitamente vinculadas ou incorporadas ao documento e anexe-as à janela picture-in-picture. Observação: esta é uma cópia ú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);
});
Processar quando a janela PiP é fechada
Ouça o evento "pagehide" da janela para saber quando a janela picture-in-picture é fechada (porque o site iniciou ou o usuário fechou manualmente). O manipulador de eventos é um bom lugar para recuperar os elementos da janela picture-in-picture, conforme mostrado aqui.
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);
});
});
Feche a janela picture-in-picture programaticamente usando o método close().
// Close the Picture-in-Picture window programmatically.
// The "pagehide" event will fire normally.
pipWindow.close();
Ouvir quando o site entra no PiP
Ouça o evento "enter" em documentPictureInPicture para saber quando uma
janela picture-in-picture é aberta. O evento contém um objeto window para acessar a janela picture-in-picture.
documentPictureInPicture.addEventListener("enter", (event) => {
const pipWindow = event.window;
});
Acessar elementos na janela PiP
Acesse elementos na janela picture-in-picture do objeto retornado por documentPictureInPicture.requestWindow() ou com 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;
}
Processar eventos da janela PiP
Crie botões e controles e responda aos eventos de entrada do usuário (como
"click"), como sempre no 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);
Redimensionar a janela PiP
Use os métodos resizeBy()
e resizeTo()
da janela para redimensionar a janela picture-in-picture. Os dois métodos exigem um gesto do usuário.
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);
Focar na janela de abertura
Use o método focus()
da janela para focar a janela de abertura na janela picture-in-picture.
Esse método exige um gesto do usuário.
const returnToTabButton = pipWindow.document.createElement("button");
returnToTabButton.textContent = "Return to opener tab";
returnToTabButton.addEventListener("click", () => {
window.focus();
});
pipWindow.document.body.append(returnToTabButton);
Modo de exibição CSS PiP
Use o modo de exibição picture-in-picture do CSS para gravar regras CSS específicas que só são aplicadas quando (parte do) o app da Web é mostrado no modo picture-in-picture.
@media all and (display-mode: picture-in-picture) {
body {
margin: 0;
}
h1 {
font-size: 0.8em;
}
}
Detecção de recursos
Para verificar se a API Document Picture-in-Picture tem suporte, use:
if ('documentPictureInPicture' in window) {
// The Document Picture-in-Picture API is supported.
}
Demonstrações
- Player VideoJS: jogue com a demonstração do player VideoJS da API Document Picture-in-Picture.
- Tomodoro, um app da Web pomodoro, aproveita a API Document Picture-in-Picture quando disponível. Consulte a solicitação de pull do GitHub.
Envie feedback
Registre problemas no GitHub com sugestões e perguntas.