A API Document Picture-in-Picture permite abrir uma janela sempre no topo que pode ser preenchida com conteúdo HTML arbitrário. Ela estende a API Picture-in-Picture para <video>, que permite apenas que um elemento HTML <video> 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 de 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 dura mais do que a 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 o rascunho inicial da especificação | Em andamento |
| 3. Coletar feedback e iterar o design | Em andamento |
| 4. Teste de origem | Concluído |
| 5. Iniciar | 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 picture-in-picture atual aceita poucos comandos e tem capacidade limitada de estilização. Com um documento completo em picture-in-picture, o site pode fornecer controles e entradas personalizados (por exemplo, legendas, playlists, barra de tempo, marcação de "Gostei" e "Não gostei" em 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 fazer uma apresentação de outra guia para a chamada, fazer anotações ou realizar 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 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 em picture-in-picture, o site pode combinar facilmente vários fluxos 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 mostram que os usuários precisam de mais maneiras de serem produtivos na Web. O recurso "Documento em picture-in-picture" oferece aos apps da Web a flexibilidade para fazer mais. Seja para edição de texto, anotações, listas de tarefas, mensagens e chat ou ferramentas de 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 será 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- Abra a janela picture-in-picture na posição e no tamanho padrão se for verdadeiro. O valor padrão é "false".
Eventos
documentPictureInPicture.onenter- Disparado 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 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 das opções se eles forem muito grandes ou 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 picture-in-picture
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. Essa é 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 for 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 gerenciador de eventos é um bom lugar para extrair os elementos da janela picture-in-picture, como 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 de forma programática 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 modo PiP
Detecte 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 picture-in-picture
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 picture-in-picture
Crie botões e controles e responda a eventos de entrada do usuário (como
"click"), como sempre em 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 picture-in-picture
Use os métodos de janela resizeBy()
e resizeTo()
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()
Window 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 picture-in-picture do CSS
Use o modo de exibição picture-in-picture do CSS para escrever regras específicas que só são aplicadas quando (parte do) o web app é 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 Picture-in-Picture de documentos é compatível, use:
if ('documentPictureInPicture' in window) {
// The Document Picture-in-Picture API is supported.
}
Demonstrações
- Player VideoJS: teste a API Picture-in-Picture de documentos demonstração do player VideoJS.
- O Tomodoro, um app da Web de pomodoro, aproveita a API Picture-in-Picture de documentos quando disponível. Consulte a solicitação de pull do GitHub.
Envie feedback
Registre problemas no GitHub com sugestões e perguntas.