ドキュメント ピクチャー イン ピクチャー API を使用すると、任意の HTML コンテンツを配置できる最前面ウィンドウを開くことができます。この API は、HTML の <video> 要素のみをピクチャー イン ピクチャー(PIP)ウィンドウに配置できる既存の <video> 用ピクチャー イン ピクチャー API を拡張したものです。
Document Picture-in-Picture API のピクチャー イン ピクチャー ウィンドウは、window.open() を使用して開かれた空白の同一オリジン ウィンドウに似ていますが、いくつかの違いがあります。
- ピクチャー イン ピクチャー ウィンドウは、他のウィンドウの上に表示されます。
- ピクチャー イン ピクチャー ウィンドウは、開いたウィンドウよりも長く表示されることはありません。
- ピクチャー イン ピクチャー ウィンドウを操作できない。
- ピクチャー イン ピクチャー ウィンドウの位置はウェブサイトで設定できません。
ステータス
| ステップ | ステータス |
|---|---|
| 1. 説明を作成する | 完了 |
| 2. 仕様の最初のドラフトを作成する | 作成中 |
| 3. フィードバックを収集して設計をイテレーションする | 作成中 |
| 4. オリジン トライアル | 完了 |
| 5. リリース | 完了(パソコン) |
ユースケース
この API は、カスタム動画プレーヤー、ビデオ会議、生産性向上アプリなど、さまざまな方法で使用できます。
カスタム動画プレーヤー
ウェブサイトは、既存の <video> 用ピクチャー イン ピクチャー API を使用してピクチャー イン ピクチャー動画エクスペリエンスを提供できますが、その機能は非常に限られています。既存の PIP ウィンドウは入力の受け付けが少なく、スタイル設定の機能も限られています。ピクチャー イン ピクチャーのドキュメント全体を使用すると、ウェブサイトはカスタム コントロールと入力(字幕、プレイリスト、再生ポイント、動画の高評価と低評価など)を提供して、ユーザーの PIP 動画エクスペリエンスを向上させることができます。
ビデオ会議
ユーザーは、ビデオ会議セッション中にブラウザタブを一時的に離れることがよくあります。たとえば、別のタブから通話にプレゼンテーションを行う場合や、メモを取る場合、その他のマルチタスクを行う場合などです。ただし、ほとんどの場合、ユーザーは通話を見たいと考えているため、これはピクチャー イン ピクチャーの理想的なユースケースです。繰り返しになりますが、現在のビデオ会議ウェブサイトで <video> のピクチャー イン ピクチャー API を使用して提供できるエクスペリエンスは、スタイルと入力が制限されています。ドキュメントのピクチャー イン ピクチャーをフルに活用すると、ウェブサイトは canvas ハックに頼ることなく、複数の動画ストリームを 1 つの PiP ウィンドウに簡単に統合し、メッセージの送信、他のユーザーのミュート、挙手などのカスタム コントロールを提供できます。
仕事効率化
調査によると、ユーザーはウェブ上で生産性を高めるためのより多くの方法を必要としています。ドキュメントのピクチャー イン ピクチャーにより、ウェブアプリはより柔軟に多くのことをこなせるようになります。テキスト編集、メモ取り、タスクリスト、メッセージングとチャット、デザインと開発ツールなど、ウェブアプリはコンテンツを常にアクセス可能な状態に保つことができます。
インターフェース
プロパティ
documentPictureInPicture.window- 現在のピクチャー イン ピクチャー ウィンドウを返します(存在する場合)。それ以外の場合は、
nullを返します。
メソッド
documentPictureInPicture.requestWindow(options)ピクチャー イン ピクチャー ウィンドウが開いたときに解決される Promise を返します。ユーザー ジェスチャーなしで呼び出された場合、Promise は拒否されます。
options辞書には、次のオプションのメンバーが含まれています。width- ピクチャー イン ピクチャー ウィンドウの初期幅を設定します。
height- ピクチャー イン ピクチャー ウィンドウの初期の高さを設定します。
disallowReturnToOpener- が true の場合、ピクチャー イン ピクチャー ウィンドウの [タブに戻る] ボタンを非表示にします。デフォルトでは false です。
preferInitialWindowPlacement- true の場合、ピクチャー イン ピクチャー ウィンドウをデフォルトの位置とサイズで開きます。デフォルトでは false です。
イベント
documentPictureInPicture.onenter- ピクチャー イン ピクチャー ウィンドウが開いたときに
documentPictureInPictureで発生します。
例
次の HTML は、カスタム動画プレーヤーと、ピクチャー イン ピクチャー ウィンドウで動画プレーヤーを開くボタン要素を設定します。
<div id="playerContainer">
<div id="player">
<video id="video"></video>
</div>
</div>
<button id="pipButton">Open Picture-in-Picture window</button>
ピクチャー イン ピクチャー ウィンドウを開く
次の JavaScript は、ユーザーがボタンをクリックして空白のピクチャー イン ピクチャー ウィンドウを開いたときに documentPictureInPicture.requestWindow() を呼び出します。返された Promise は、ピクチャー イン ピクチャー ウィンドウの JavaScript オブジェクトで解決されます。動画プレーヤーは 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);
});
ピクチャー イン ピクチャー ウィンドウのサイズを設定する
ピクチャー イン ピクチャー ウィンドウのサイズを設定するには、documentPictureInPicture.requestWindow() の width オプションと height オプションを理想的な PiP ウィンドウ サイズに設定します。オプションの値が大きすぎたり小さすぎたりして、使いやすいウィンドウ サイズに収まらない場合、Chrome はオプションの値を小さくすることがあります。
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);
});
PIP ウィンドウの [タブに戻る] ボタンを非表示にする
ユーザーがオープナー タブに戻るためのボタンをピクチャー イン ピクチャー ウィンドウに表示しないようにするには、documentPictureInPicture.requestWindow() の disallowReturnToOpener オプションを 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,
});
});
PiP をデフォルトの位置とサイズで開く
以前のピクチャー イン ピクチャー ウィンドウの位置やサイズを再利用しないようにするには、documentPictureInPicture.requestWindow() の preferInitialWindowPlacement オプションを true に設定します。
pipButton.addEventListener("click", async () => {
// Open a Picture-in-Picture window in its default position / size.
const pipWindow = await documentPictureInPicture.requestWindow({
preferInitialWindowPlacement: true,
});
});
スタイルシートを PiP にコピーする
元のウィンドウからすべての CSS スタイルシートをコピーするには、ドキュメントに明示的にリンクされているか埋め込まれている styleSheets をループ処理し、ピクチャー イン ピクチャー ウィンドウに追加します。これは 1 回限りのコピーです。
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);
});
PIP ウィンドウが閉じられたときの処理
ウィンドウの "pagehide" イベントをリッスンして、ピクチャー イン ピクチャー ウィンドウが閉じられたタイミング(ウェブサイトによって開始されたか、ユーザーが手動で閉じたか)を把握します。イベント ハンドラは、次に示すように、ピクチャー イン ピクチャー ウィンドウから要素を取り出すのに適した場所です。
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);
});
});
close() メソッドを使用して、ピクチャー イン ピクチャー ウィンドウをプログラムで閉じます。
// Close the Picture-in-Picture window programmatically.
// The "pagehide" event will fire normally.
pipWindow.close();
ウェブサイトが PiP に入ったときにリッスンする
documentPictureInPicture の "enter" イベントをリッスンして、ピクチャー イン ピクチャー ウィンドウが開いたタイミングを把握します。このイベントには、ピクチャー イン ピクチャー ウィンドウにアクセスするための window オブジェクトが含まれています。
documentPictureInPicture.addEventListener("enter", (event) => {
const pipWindow = event.window;
});
PiP ウィンドウの要素にアクセスする
ピクチャー イン ピクチャー ウィンドウの要素には、documentPictureInPicture.requestWindow() が返すオブジェクトから、または 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;
}
PiP ウィンドウからのイベントを処理する
ボタンやコントロールを作成し、JavaScript でユーザーの入力イベント("click" など)に応答します。
// 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);
PIP ウィンドウのサイズを変更する
resizeBy() ウィンドウ メソッドと resizeTo() ウィンドウ メソッドを使用して、ピクチャー イン ピクチャー ウィンドウのサイズを変更します。どちらのメソッドでもユーザー ジェスチャーが必要です。
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() ウィンドウ メソッドを使用して、ピクチャー イン ピクチャー ウィンドウからオープナー ウィンドウにフォーカスします。このメソッドにはユーザー ジェスチャーが必要です。
const returnToTabButton = pipWindow.document.createElement("button");
returnToTabButton.textContent = "Return to opener tab";
returnToTabButton.addEventListener("click", () => {
window.focus();
});
pipWindow.document.body.append(returnToTabButton);
CSS PiP 表示モード
CSS の picture-in-picture 表示モードを使用して、ウェブアプリの一部がピクチャー イン ピクチャー モードで表示される場合にのみ適用される特定の CSS ルールを記述します。
@media all and (display-mode: picture-in-picture) {
body {
margin: 0;
}
h1 {
font-size: 0.8em;
}
}
特徴検出
Document Picture-in-Picture API がサポートされているかどうかを確認するには、次のコードを使用します。
if ('documentPictureInPicture' in window) {
// The Document Picture-in-Picture API is supported.
}
デモ
- VideoJS プレーヤー: Document Picture-in-Picture API の VideoJS プレーヤーのデモで試してみましょう。
- ポモドーロ ウェブアプリの Tomodoro は、利用可能な場合に Document Picture-in-Picture API を活用しています。GitHub の pull リクエストをご覧ください。
フィードバックをお寄せください
提案や質問がある場合は、GitHub で Issue を作成してください。