0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Qiita全国学生対抗戦Advent Calendar 2024

Day 24

Document Picture-in-Picture APIを使ってみた 【JavaScript】

Last updated at Posted at 2024-12-24

はじめに

開いてくださりありがとうございます!普段は大学で化学を専攻してます𝕏 | @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);
   });

asyncawaitです。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したいページがある場合は使ってみて下さい

レイアウトが崩れたり動作しない場合があります

Bookmarklet(.cloneNode(true))
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「-」で拡大縮小できます

circlock
circlock

cssをインライン記述にすることでPiP中でもスタイルを変更できます。
PiPウィンドウの秒表示の::selectionはpostMessageで子ウィンドウに色を送信して無理くり適用させてます。


また、dcument PiP APIが使用不可の環境の場合、canvasに描画させてからそれをvideo要素にすることで従来の方法のPiPを開始してます

canvas Picture-in-Picture
PiP
  // 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();
        }
    });

text-counter
text-counter.png




またGoogle MeetやSpotifyも活用しているようです
Google Meet
googlemeet.png
(Google Meetではタブが切り替わった際にPiPを自動開始できるようです この実装方法が分かる方は教えて下さい....)


Spotify
spotify.png


PiP Windowにマウスホバー
spotifyhover.png

Premiumじゃないとできない(?)またアプリ版でもPiPできます


他の作業中にもすぐ確認できるのは良いですね
またメインウィンドウをクリックしてもPiPを使うとウィンドウが後ろに隠れないところがvery good!:thumbsup:

私は講義の残り時間を計算するページを作ってそれをPiPで表示させることで便利に使ってます。講義は集中してますよ、えぇもちろん

まとめ

※このAPIは今後仕様が変更する可能性があるのでお気を付け下さい

以上Document Picture-in-Picture APIの紹介でした!
今後この機能を使ったサイトが増えてくと嬉しいですね。またこの機能を使ってサイトを作ったら是非教えて下さい!

参考

おわりに

初めて記事をしかもMarkdown形式で書いたので拙い部分があると思いますがここまで読んで頂きありがとうございます!
記事を共有してくださると大変喜びます!



それではあなたも良いPiPライフを!:grinning: :wave:

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?