Picture-in-Picture APIで画像表示
昨今のブラウザではPicture-in-Picture APIを使いPinP表示する事が簡単にできますが、現状対応しているコンテンツは動画のみです。
基本的にvideo
要素に表示されている内容のみがPinP表示されるわけですが、canvas
要素を用いcaptureStream()
を行えば自由なコンテンツをPinP表示する事が可能になります。
たとえば画像をPinP表示する例を示します。
以下の様な特定の画像を表示しつつ、ボタンをクリックするとPinP表示をトグルできるHTMLとJSを用意します。
<imgid="pip-image-element"src="https://source.unsplash.com/400x300?random"style="width: 400px; height: 300px;"><button id="pip-button-element">PinP Toggle</button>
interface CanvasElement extends HTMLCanvasElement { captureStream(frameRate?: number): MediaStream}
class PinpImage { pipImageElement: HTMLImageElement | null pipButtonElement: HTMLButtonElement | null
image: HTMLImageElement
constructor() { this.pipImageElement = document.querySelector('#pip-image-element') this.pipButtonElement = document.querySelector('#pip-button-element')
this.image = new Image()
if (!this.pipImageElement) { return }
this.image.crossOrigin = 'Anonymous' this.image.addEventListener('load', () => this.imageLoaded(), false) this.image.src = this.pipImageElement.src }
imageLoaded(): void { const canvas = <CanvasElement>document.createElement('canvas') canvas.height = this.image.height canvas.width = this.image.width
// Draw something to canvas. const ctx = canvas.getContext('2d') if (!ctx) { return }
ctx.scale(1, 1) ctx.drawImage(this.image, 0, 0)
const video = document.createElement('video') video.muted = true video.autoplay = true video.srcObject = canvas.captureStream(60) video.play()
this.pipButtonElement?.addEventListener('click', async () => { try { if (video !== document.pictureInPictureElement) { await video.requestPictureInPicture() } else { await document.exitPictureInPicture() } } catch (error) { // some code } finally { // some code } }) }}
window.addEventListener('load', () => { new PinpImage()})
注目する箇所は以下です。
- 画像を
drawImage()
でcanvas
要素に表示 - それを
captureStream()
でvideo
要素のメディアソースとして指定 - ボタンクリックで
video
要素をPinP表示
canvasにて表現できるものであれば比較的容易にPinP表示もできる事が分かります。
アイデア次第でPinPの世界も広がりそうです。
参考: https://www.w3.org/TR/picture-in-picture/
参考: https://googlechrome.github.io/samples/picture-in-picture/audio-playlist
参考: https://sbfl.net/blog/2021/04/30/javascript-html-picture-in-picture/