オリジントライアルになったDocument Picture-in-Picture APIを試してみよう
Chrome111 から Document Picture-in-Picture API がオリジントライアルで試せるようになりました。
Picture-in-Picture とは?
次の画像のように、画面の一部に別でウインドウを表示することを Picture-in-Picture といいます。
動画を右下で流しつつ、別の WEB サイトを確認するなど、1 つの画面で 2 つのウインドウが表示できます。
Document Picture-in-Picture API とは?
今回新たにオリジントライアルに追加された Document Picture-in-Picture API とは別に Picture-in-Picture API の仕様が Media Working Group によって策定されています。
この Picture-in-Picture API では使用できる要素が <video>
のみでしたが、 Document Picture-in-Picture API では <video>
以外の要素も使用できるようになります。
Document Picture-in-Picture API をどのように使うか
実際に Document Picture-in-Picture API を使って Picture-in-Picture のウインドウの中にストップウォッチを表示してみます。
オリジントライアルのトークンが有効な間は、次のリンクから実装したものを確認できます。
Picture-in-Picture のウインドウにストップウォッチを表示
実装したコードはnus3/ui-labsにあります。
Picture-in-Picture ウインドウを表示する
Document Picture-in-Picture API では documentPictureInPicture
を使って Picture-in-Picture の操作をします。
documentPictureInPicture.requestWindow()
を実行することで Picture-in-Picture のウインドウが表示されます。
requestWindow()
はウインドウが表示された際に resolve する Promise を返します。この Promise は、クリックなどのユーザー操作時以外の場合には reject します。
// ボタンをクリックした時にPicture-in-Pictureのウインドウを表示する
button.addEventListener("click", async () => {
await documentPictureInPicture.requestWindow();
});
// ユーザー操作時以外の場合は以下のようなエラーを返します
documentPictureInPicture.requestWindow();
// Uncaught (in promise) DOMException: Failed to execute 'requestWindow' on 'DocumentPictureInPicture': Document PiP requires user activation
元のウインドウで定義した CSS を Picture-in-Picture ウインドウにもコピーする
requestWindow()
には引数にオプションを指定できます。オプションの 1 つに copyStyleSheets
があり、これを true にすると元のウインドウの CSS がコピーされます。
button.addEventListener("click", async () => {
await documentPictureInPicture.requestWindow({
copyStyleSheets: true,
});
});
この他にオプションでは Picture-in-Picture のアスペクト比と幅、高さを指定できます。
Picture-in-Picture ウインドウに表示する要素を追加する
requestWindow()
か documentPictureInPicture.window
を使うことで、Picture-in-Picture ウインドウの Window
インスタンスを取得できます。
取得した Window
インスタンスに対して要素を追加することで、Picture-in-Picture ウインドウに追加した要素を表示できます。
<div id="timerWrapper">
<span id="time">00:00:00.000</span>
<!-- ... -->
</div>
button.addEventListener("click", async () => {
// Picture-in-Picture ウインドウに表示したい要素を取得
const player = document.querySelector("#timerWrapper");
// Picture-in-Picture ウインドウのインスタンスをrequestWindow()の返り値として取得
const pipWindow = await documentPictureInPicture.requestWindow();
// Picture-in-Picture ウインドウに表示したい要素を追加
pipWindow.document.body.append(player);
});
// Picture-in-Picture ウインドウが表示されている場合は、下記でも取得できる
const pipWindow = documentPictureInPicture.window
Picture-in-Picture ウインドウが閉じる際の処理を追加する
Picture-in-Picture ウインドウは閉じるアイコンをクリックするか、close()
メソッドを実行することで閉じることができます。
const pipWindow = await documentPictureInPicture.requestWindow();
pipWindow.close();
また、Picture-in-Picture ウインドウの Window
インスタンスに対して unload
イベントを登録することでウインドウが閉じた際の処理を追加できます。
button.addEventListener("click", async () => {
// Picture-in-Picture ウインドウのインスタンスをrequestWindow()の返り値として取得
const pipWindow = await documentPictureInPicture.requestWindow();
pipWindow.addEventListener("unload", (event) => {
// Picture-in-Picture ウインドウが閉じた際の処理をここに書ける
});
});
ストップウォッチを Picture-in-Picture ウインドウに表示する
今回は、requestWindow()
で取得した Picture-in-Picture ウインドウのインスタンスに対して、ストップウォッチの要素を追加したり、イベントハンドラの追加、削除をしています。
button.addEventListener("click", async () => {
// ストップウォッチの要素を取得
const player = document.querySelector("#timerWrapper");
// Picture-in-Picture ウインドウを表示し、元のCSSをコピー
const pipWindow = await documentPictureInPicture.requestWindow({
copyStyleSheets: true,
});
// Picture-in-Picture ウインドウにストップウォッチ要素を表示
pipWindow.document.body.append(player);
// Picture-in-Picture ウインドウ内のタイマー部分の要素を取得
const time = pipWindow.document.getElementById("time");
// startボタンを押された時のイベントハンドラを定義
const handleStart = () => {
start(time);
};
// Picture-in-Picture ウインドウ内のスタートボタンに対してクリックイベントを登録
const startBtn = pipWindow.document.getElementById("start");
startBtn?.addEventListener("click", handleStart);
pipWindow.addEventListener("unload", (event) => {
// Picture-in-Picture ウインドウが閉じられる時にスタートボタンのクリックイベントを削除
startBtn?.removeEventListener("click", handleStart);
});
});
Document Picture-in-Picture API 関連リンク
-
Picture-in-Picture API
- ステータスは Editors' Draft
- Media Working Groupが進めている
- https://developer.chrome.com/blog/watch-video-using-picture-in-picture/
-
Document Picture-in-Picture API
- ステータスは Unofficial Draft
- Web Incubator CGが進めている
Special Thanks
この記事を書くにあたり、ストップウォッチ部分の実装は ChatGPT さんにお願いしました。
最後に
まだ仕様の策定段階ですが、Document Picture-in-Picture API は動画だけでなく、今回実装したストップウォッチのように色々な場面で利用できそうでおもしろいですね。
Chrome111 であればフラグを有効にするだけで簡単にローカルで試せるので、興味のある方はぜひ試してみてください。
Discussion