2023-09-10

Document Picture-in-Picture APIで簡単なWebアプリを作成

目次

Document Picture-in-Picture APIについて

最新バージョンのChrome116でDocument Picture-in-Picture APIが実装されました。

Picture-in-Picture API自体はすでに実装されていたのですが、使用できるのはvideo要素のみでした。 今回のアップデートにより、video要素に限らず、ウェブページ上の任意の要素をPicture-in-Pictureモードで表示できるようになりました。

作成したWebアプリ

Document Picture-in-Picture APIの機能を使って、簡単なWebアプリを作成しました。 テキストエリアに入力した内容をPicture in Pictureモードで表示します。 それ以外の機能としては、文字色と文字の大きさを簡単に変えられるようになっていることと、1/319の確率で宇宙一かわいいうさぎの画像が表示されます。(強制的に表示させる隠しコマンドもある。)

MEMO IN

コードの紹介

今回NuxtでつくったのでVue.jsのコードで紹介します。

JavaScriptのコードは参考サイトを参照してください。

ウインドウを表示する

requestWindow()にはオプションとしてwidthheightを渡しています。

<script lang="ts" setup>
...
const inputVal = ref<string>('')
const pipContainer = ref<HTMLElement | null>(null)
const pipBody = ref<HTMLElement | null>(null)
const pipWindow = ref<WindowWithPictureInPicture | null>(null)
const isPip = ref<boolean>(false)
const onOpen = async () => {
  isPip.value = true
  const option = {
    width: 300,
    height: 300,
  }
  // Picture-in-Picture ウィンドウを開く.
  pipWindow.value = await window.documentPictureInPicture.requestWindow(option)
  // 入力されたテキストを Picture-in-Picture ウィンドウに挿入する.
  pipWindow.value.document.body.append(pipBody.value)
}
</script>
<template>
  <main>
    <textarea v-model="inputVal" ></textarea>
    <div ref="pipContainer">
      <div ref="pipBody">{{ inputVal }}</div>
    </div>
    <button v-if="!isPip" type="button" @click="onOpen" aria-pressed="false">開く</button>
    <button v-else type="button" @click="onClose" aria-pressed="true">閉じる</button>
  </main>
</template>

ウインドウを閉じる

<script lang="ts" setup>
const onClose = async () => {
  isPip.value = false
  // Picture-in-Picture ウィンドウを閉じる.
  pipWindow.value?.close()
}
</script>

ウインドウを閉じた時のイベント

<script lang="ts" setup>
const onOpen = async () => {
  ...
  pipWindow.value.addEventListener('pagehide', (event: Event) => {
    pipContainer.value?.append(pipBody.value as string | Node)
    isPip.value = false
  })
}
</script>

Demo

ここまでのコードをまとめたものは下記を参考にしてください。

注意点

Picture in Pictureウィンドウは元ウィンドウからCSSが引き継がれません。そのためJavaScriptCSSをコピーする必要があります。

以前はオプションでcopyStyleSheetsを指定するのみでよかったのですが、議論の末に削除されたという経緯があります。

実現できていないこと・課題

  • ウィンドウが300 ✕ 300 より小さくはならない
  • Picture in Pictureのキーボード操作を理解していない。

まとめ

Chrome116で実装されたDocument Picture-in-Picture APIについて紹介しました。
現在はChrome,Edgeのみしか使用できませんが、helpやtipsなどの表示であったり、今回作成したWebアプリのように、常にデスクトップの見える位置に配置するといった使い方で、利用価値のある場面もあるのかなと思いました。

参考