「動画」だけでなく、すべての要素でピクチャー イン ピクチャーで使用可能

François Beaufort
François Beaufort

対応ブラウザ

  • Chrome: 116。 <ph type="x-smartling-placeholder">
  • Edge: 116。 <ph type="x-smartling-placeholder">
  • Firefox: サポートされていません。 <ph type="x-smartling-placeholder">
  • Safari: サポートされていません。 <ph type="x-smartling-placeholder">

ソース

Document Picture-in-Picture API を使用すると、任意の HTML コンテンツを表示する常時表示のウィンドウを開くことができます。これは、HTML の <video> 要素のみをピクチャー イン ピクチャー ウィンドウに配置できるようにする既存の <video> 用 Picture-in-Picture API を拡張します。

Document Picture-in-Picture API の ピクチャー イン ピクチャー ウィンドウは、window.open() で開いた空白の同一オリジン ウィンドウと似ていますが、次の点が異なります。

  • ピクチャー イン ピクチャー ウィンドウは、他のウィンドウの上にフロート表示されます。
  • ピクチャー イン ピクチャー ウィンドウが開始ウィンドウより長くなることはありません。
  • ピクチャー イン ピクチャー ウィンドウは移動できません。
  • ピクチャー イン ピクチャーのウィンドウの位置はウェブサイトで設定できません。
で確認できます。 <ph type="x-smartling-placeholder">
</ph> Sintel の予告編動画を再生しているピクチャー イン ピクチャー ウィンドウ。
Document Picture-in-Picture API で作成されたピクチャー イン ピクチャーのウィンドウ(デモ)。

現在のステータス

ステップ ステータス
1. 説明を作成 完了
2. 仕様の初期ドラフトを作成する 作成中
3. フィードバックの収集と設計の反復処理 作成中
4. オリジン トライアル 完了
5. 導入 完了(パソコン)

ユースケース

カスタム動画プレーヤー

ウェブサイトは既存の <video> 用 Picture-in-Picture API を使用して、ピクチャー イン ピクチャーでの動画エクスペリエンスを提供できますが、制限は非常に限定的です。既存のピクチャー イン ピクチャー ウィンドウは入力が少なく、スタイル設定機能に制限があります。完全なドキュメント イン ピクチャーで、ウェブサイトでカスタム コントロールと入力機能(字幕、再生リスト、タイムスクラバー、動画に高評価や低評価を付けるなど)を提供して、ユーザーのピクチャー イン ピクチャー動画のエクスペリエンスを向上させることができます。

ビデオ会議

ビデオ会議セッション中に、通話を表示したいユーザーは別のタブを表示する、マルチタスクを行っているなど、ユーザーがブラウザタブを離れることが多いため、これはピクチャー イン ピクチャーの主要なユースケースです。繰り返しになりますが、現在のところ、ビデオ会議のウェブサイトが <video> の Picture-in-Picture API を介して提供できるエクスペリエンスは、スタイルと入力が制限されています。ピクチャー イン ピクチャーでドキュメント全体を作成することで、ウェブサイトはキャンバス ハッキングに頼ることなく、複数の動画ストリームを 1 つの PIP ウィンドウに簡単に結合できます。また、メッセージの送信、別のユーザーのミュート、挙手などのカスタム コントロールも利用できます。

仕事効率化

調査によれば、ユーザーはウェブで生産性を高めるために、もっと多くの方法を必要としていることがわかっています。ピクチャー イン ピクチャーでドキュメントを作成すると、ウェブアプリでより多くのことを柔軟に処理できるようになります。テキスト編集、メモ作成、タスクリスト、メッセージング、チャット、デザイン&開発ツールなど、ウェブアプリのコンテンツにいつでもアクセスできます。

インターフェース

プロパティ

documentPictureInPicture.window
現在のピクチャー イン ピクチャー ウィンドウを返します(存在する場合)。それ以外の場合は、null を返します。

メソッド

documentPictureInPicture.requestWindow(options)

ピクチャー イン ピクチャー ウィンドウが開かれたときに解決される Promise を返します。 ユーザー操作なしで呼び出された場合、Promise は拒否されます。 options ディクショナリには、次のオプションのメンバーが含まれます。

width
ピクチャー イン ピクチャー ウィンドウの初期の幅を設定します。
height
ピクチャー イン ピクチャー ウィンドウの初期の高さを設定します。
disallowReturnToOpener
[タブに戻る] が非表示になります] ボタンをクリックします。デフォルトでは 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 オプションを目的のピクチャー イン ピクチャー ウィンドウ サイズに設定します。ユーザー フレンドリーなウィンドウ サイズに収まらない場合は、オプション値が大きすぎるか小さすぎる場合、オプションの値がクランプされることがあります。

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

[タブに戻る] を非表示にする[ピクチャー イン ピクチャー] ウィンドウの

ユーザーがオープナー タブに戻ることができるピクチャー イン ピクチャー ウィンドウのボタンを非表示にするには、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,
  });
});

ピクチャー イン ピクチャー ウィンドウにスタイルシートをコピーする

元のウィンドウからすべての 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);
});

ピクチャー イン ピクチャー ウィンドウが閉じたときに処理する

ウィンドウの "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();

ウェブサイトがピクチャー イン ピクチャーに切り替わったときに音声を聞く

documentPictureInPicture"enter" イベントをリッスンして、ピクチャー イン ピクチャー ウィンドウが開かれたことを把握します。このイベントには、ピクチャー イン ピクチャー ウィンドウにアクセスするための window オブジェクトが含まれています。

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

ピクチャー イン ピクチャー ウィンドウの要素にアクセスする

ピクチャー イン ピクチャー ウィンドウの要素にアクセスするには、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;
}

ピクチャー イン ピクチャー ウィンドウからのイベントを処理する

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

ピクチャー イン ピクチャー ウィンドウのサイズを変更する

ピクチャー イン ピクチャー ウィンドウのサイズを変更するには、ウィンドウ メソッド 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 ピクチャー イン ピクチャーの表示モード

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 リクエストを参照)。

<ph type="x-smartling-placeholder">
</ph> ポモドーロ ウェブアプリ Tomodoro のスクリーンショット。
トモドーロのピクチャー イン ピクチャー ウィンドウ

フィードバック

ご提案やご質問がございましたら、GitHub で問題を報告してください。

謝辞

ヒーロー画像作成者: Jakob Owens