はじめに
開いてくださりありがとうございます!普段は大学で化学を専攻してます𝕏 | @jima_jimaxです。
今回はJavaScriptのPicture in PictureできるWeb APIを使ってみます。
この記事を見ているということは少しでも興味があると言うことですよね?
Document Picture-in-Picture APIとは??
Document Picture-in-Picture API
とはChromeでは2023年8月に116で追加されたvideo
要素以外にもPicture-in-Picture(PiP)出来るようにしたものです。
PiPを使えば常にウィンドウを最前面表示にできるので動画以外にも使えるようになったのはめちゃめちゃ嬉しいですよね!!
このAPIを使っておしゃれな(?)Web時計と文字数カウントを作ってみたので是非使って下さい↓
早速使ってみよう
フレームワークやライブラリは 分からないので 一切使わないVanilla.js
でやります!
1. 利用可能か判別
以下を使って利用可能か判別することができます
if ("documentPictureInPicture" in window) {
// document PiP APIが利用可能な場合の処理
} else {
// document PiP APIが利用不可な場合の処理
}
2. PiP Windowを開く
pipButton.addEventListener("click", async () => {
// PiP Windowに追加したい要素
const player = document.querySelector("#");
// PiP Windowを開く
const pipWindow = await documentPictureInPicture.requestWindow(options);
// 要素をPiP Windowに追加
pipWindow.document.body.append(player);
});
async
、await
です。options
にはwidth, height, disallowReturnToOpener, preferInitialWindowPlacementを指定できます。
width
, height
,はウィンドウの初期サイズ、
disallowReturnToOpener
はtrueにするとウィンドウ上の戻るボタンを消せます。
ウィンドウは通常2回目以降開く場合、前回閉じた位置で開かれますがpreferInitialWindowPlacement
をtrueにすることで毎回デフォルトの位置で開くことができます。
私が作ったページではウィンドウに要素を"移動"
していますが、"コピー"
することもできます
後述しているブックマークレットでは.cloneNode(true)
してます
3. PiP Windowを閉じる
要素は自動で親要素へと戻らないので親要素に戻す必要があります。
// 開く関数に記述
pipContainer = player.parentNode;
// 閉じる関数に記述
const player = pipWindow.document.querySelector("#");
pipContainer.append(player);
pipWindow.close();
4. おまけ
以下のブックマークレットを使えばdocument.documentElement要素をコピーしてどのページでもパワーでPiPすることができます。どうしてもPiPしたいページがある場合は使ってみて下さい
レイアウトが崩れたり動作しない場合があります
javascript:(()=>{if(!("documentPictureInPicture"in window)){alert("この環境はDocument Picture-in-Picture APIをサポートしていません");return;}const pipcheck=confirm("Picture-in-Picture表示にしますか?\n(ページレイアウトが崩れたり正常に動作しない可能性があります)");if(pipcheck){(async()=>{try{const player=document.documentElement.cloneNode(true);const pipWindow=await documentPictureInPicture.requestWindow({disallowReturnToOpener:true,preferInitialWindowPlacement:true,width:450,height:400});pipWindow.document.body.append(player);}catch(err){alert("PiPを開始出来ませんでした\n\n"+err.message);}})();}})();
やはり暴力・・・・‼暴力は全てを解決する・・・・‼
使用例
私が作ったページでは時計部分や文字を入れるフィールド部分をPiPできるので是非お試し下さい
時計についてPiP以外に関することはGitHubの[README]をご覧下さい
動作は
Windows: Chrome, Vivaldi
Android: Chrome
で確認を行ったためApple系デバイスやその他ブラウザは確認していません。
PiPウィンドウをフォーカス中にCtrl + 「+」or「-」
で拡大縮小できます
cssをインライン記述にすることでPiP中でもスタイルを変更できます。
PiPウィンドウの秒表示の::selectionはpostMessageで子ウィンドウに色を送信して無理くり適用させてます。
また、dcument PiP APIが使用不可の環境の場合、canvas
に描画させてからそれをvideo
要素にすることで従来の方法のPiPを開始してます
canvas Picture-in-Picture
// canvas Picture-in-Picture
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const scaleFactor = 3; // 3倍で描画させて解像度を3倍にする
canvas.width = 300 * scaleFactor;
canvas.height = 300 * scaleFactor;
canvas.style.width = "300px";
canvas.style.height = "300px";
ctx.scale(scaleFactor, scaleFactor);
const stream = canvas.captureStream(30);
const video = document.createElement("video");
video.srcObject = stream;
pipButton.addEventListener("change", async () => {
await video.play();
if (document.pictureInPictureElement) {
await document.exitPictureInPicture();
} else {
await video.requestPictureInPicture();
}
});
またGoogle MeetやSpotifyも活用しているようです
Google Meet
(Google Meetではタブが切り替わった際にPiPを自動開始できるようです この実装方法が分かる方は教えて下さい....)
Spotify
PiP Windowにマウスホバー
Premiumじゃないとできない(?)またアプリ版でもPiPできます
他の作業中にもすぐ確認できるのは良いですね
またメインウィンドウをクリックしてもPiPを使うとウィンドウが後ろに隠れないところがvery good!
私は講義の残り時間を計算するページを作ってそれをPiPで表示させることで便利に使ってます。講義は集中してますよ、えぇもちろん
まとめ
※このAPIは今後仕様が変更する可能性があるのでお気を付け下さい
以上Document Picture-in-Picture APIの紹介でした!
今後この機能を使ったサイトが増えてくと嬉しいですね。またこの機能を使ってサイトを作ったら是非教えて下さい!
参考
- 「動画」だけでなく、すべての要素でピクチャー イン ピクチャーで使用可能
https://developer.chrome.com/docs/web-platform/document-picture-in-picture?hl=ja - オリジントライアルになったDocument Picture-in-Picture APIを試してみよう
https://zenn.dev/cybozu_frontend/articles/picture-in-picture-api - ChromeのDocument Picture-in-Picture APIを試してみた
https://zenn.dev/voiceapplab/articles/2b90180c38af9d - 記事をPicture-in-Pictureで読めるようにしてみた
https://blog.stin.ink/articles/article-in-picture-in-picture
おわりに
初めて記事をしかもMarkdown形式で書いたので拙い部分があると思いますがここまで読んで頂きありがとうございます!
記事を共有してくださると大変喜びます!
それではあなたも良いPiPライフを!