Frontend Weekly 2023-08-15 Chrome 116
Chrome 116のDocument Picture-in-Picture API、CSS Animation、CSS Motion Path、Enabled Privacy Sandbox APIについて紹介する。
Document Picture-in-Picture API
Document Picture-in-Picture APIは、video要素のみに適用できるPicture-in-Picture APIと異なり、任意の要素を小窓で表示することが出来ます。
const button = document.querySelector("#open-button");
button.addEventListener("click", async () => {
const player = document.querySelector("#player");
const pipWindow = await documentPictureInPicture.requestWindow({
// initialAspectRatio: 1,
width: player.width,
height: player.height,
});
pipWindow.document.body.append(player);
});
Picture-in-Picture API
Picture-in-Picture APIは、video要素を小窓で表示するためのAPIです。
const button = document.querySelector("#open-button");
const video = document.querySelector("#video");
button.addEventListener("click", () => {
video.requestPictureInPicture();
});
Picture-in-Picture APIとの比較
Document Picture-in-Picture APIは、Picture-in-Picture APIの拡張ではなく似たような異なるAPIです。
Document Picture-in-Picture API | Picture-in-Picture API | |
---|---|---|
対象となる要素 | 任意の要素 | video要素 |
Picture-in-Pictureを開くメソッド | documentPictureInPicture.requestWindow() | video.requestPictureInPicture() |
実行にクリックなどユーザー行動が必須か | 必須 | 必須 |
iframe内での実行 | 不可 | 不可 |
同時に開ける数 | 1個。個数はPicture-in-Picture APIと共有 | 1個。個数はDocument Picture-in-Picture APIと共有 |
Picture-in-Pictureした要素の状態 | 要素が消える。Picture-in-Pictureを閉じても要素は戻らない。 | 要素は消えず代替表示がされる。picture-in-picture擬似クラスでスタイルを制御できる。 |
Document Picture-in-Picture APIは、任意の要素ではなく新たなDocumentをPicture-in-Pictureしていると考えると理解しやすいと思います。
Document Picture-in-Picture APIでは勝手に要素が復帰しない
Picture-in-Picture APIの場合と異なり、Document Picture-in-Picture APIではPicture-in-Pictureされた要素は、勝手には戻りません。
次のようにPicture-in-PictureのWindowのunloadイベントをトリガーにして、そのWindowにある表示した要素を取得し戻すようなコードを書く必要があります。
button.addEventListener("click", async () => {
const playerContainer = document.querySelector("#playerContainer");
const player = document.querySelector("#player");
const pipWindow = await documentPictureInPicture.requestWindow({
width: player.width,
height: player.height,
});
pipWindow.document.body.append(player);
pipWindow.addEventListener("unload", event => {
const pipPlayer = event.target.querySelector("#player");
playerContainer.append(pipPlayer);
});
});
Picture-in-Picture内にCSSを適用する
実験的な機能として導入されたときは存在していたcopyStyleSheetsオプションは削除されています。そのため、手軽にCSSをコピーして持っていくような方法は存在しません。
https://github.com/WICG/document-picture-in-picture/issues/12
削除されたcopyStyleSheetsオプションの挙動を真似したい場合。
// const pipWindow = await documentPictureInPicture.requestWindow({
// width: player.width,
// height: player.height,
// });
[...document.styleSheets].forEach(styleSheet => {
try {
const cssRules = [...styleSheet.cssRules]
.map(rule => rule.cssText)
.join("");
const style = document.createElement("style");
style.textContent = cssRules;
pipWindow.document.head.appendChild(style);
} catch (e) {
const link = document.createElement("link");
link.rel = "stylesheet";
link.type = styleSheet.type;
link.media = styleSheet.media;
link.href = styleSheet.href;
pipWindow.document.head.appendChild(link);
}
});
// pipWindow.document.body.append(player);
特に言及されていませんが、個人的にはPicture-in-Picture用のスタイルを別途用意してあげた方が、無駄なスタイルを大量に渡さなく済むため良いように思います。
実装例
https://stackblitz.com/edit/js-mrokk8?file=index.js
CSS Animationでdisplayとcontent-visibilityが適用可能に
今まではdisplayやcontent-visibilityをkeyframeに書いても適用されず、次のようなコードでは透明になるだけでしたが、これからはdisplayが適用されるようになったため100%になった段階で要素が消えます。段階的にdisplayやcontent-visibilityが変化するわけではありません。
@keyframes fade-out {
100% {
display: none;
opacity: 0;
}
}
.target {
display: block;
animation: fade-out 2s forwards;
}
今までこれを実現するためだけに、JavaScriptを利用してclassNameやstyleを付け替えるような実装が良く行われていました。
以下の記事では、これとChrome 117で予定されている新機能によってスムーズな出入りにアニメーションが実現できると言われています。
https://developer.chrome.com/blog/entry-exit-animations/
実装例
https://stackblitz.com/edit/js-hodtra?file=style.css
CSS Motion Path
以前からpath()
はほとんどのブラウザで利用できましたが、circle()
、ellipse()
、rect()
、inset()
、xywh()
、polygon()
、ray()
、url()
などを利用したパスの指定ができるようになりました。
https://developer.mozilla.org/ja/docs/Web/CSS/CSS_motion_path
実装例
サンプルを見た方がどのようなことが簡単に出来るようになったのか分かりやすいです。
https://stackblitz.com/edit/js-cz9n1h?file=style.css
Enabled Privacy Sandbox API ≥ 99%
今回のリリースでもChrome 115のリリースでも触れられていませんでしたが、予定通りに進んでいれば既にほとんどのChromeでPrivacy Sandbox関連のAPIが有効化されているはずです。