瀏覽器中的畫中畫(Picture-in-Picture)模式及其 API

各個國產殼子瀏覽器也爭相內置“視頻彈窗播放”的功能,比如當年的火狐中國版:

瀏覽器中的畫中畫(Picture-in-Picture)模式及其 API

火狐魔鏡

這麼多年過去了,正統瀏覽器們終於要內置這個功能了,而且還有配套的 API 給開發者使用。

WICG,全名為 Web Incubator Community Group(Web 孵化器社區小組),主要成員為 Chrome 的工程師們,他們從一年前開始標準化這個能讓視頻彈窗播放的特性,起名為 Picture-in-Picture(畫中畫),縮寫為 PiP。

Chrome 從今年年初開始著手實現,到本文撰稿時,已經實現的差不多了。這篇文章將主要講兩方面:Chrome 當前實現的 PiP 交互是怎麼樣的,以及有哪些 API 讓我們開發者使用。

瀏覽器中的畫中畫(Picture-in-Picture)模式及其 API

PiP 相關 API

1. video 元素新增的方法 requestPictureInPicture()

請求讓該 video 元素進入畫中畫模式,返回一個 promise,如果沒有異常,這個 promise 包的值會是一個 PictureInPictureWindow對象,這個對象就代表彈出的那個 PiP 窗口,後面會單獨講它的 API。

async function openPiP(video) { try { const pipWindow = await video.requestPictureInPicture() // 進入畫中畫模式 ... } catch (e) { console.error(e) // 處理異常 }})

哪些情況下進入畫中畫模式會失敗?一共有 5 種情況:

  1. 操作系統不支持、或者用戶通過瀏覽器選項禁用了此功能,此時 document.pictureInPictureEnabled 屬性會返回 false視頻文件錯誤、或者沒有視頻流只有音頻流此次請求不是由用戶操作觸發的,比如用戶沒有點擊任何按鈕,頁面自動執行該方法,會被當做惡意行為攔截掉當前頁面通過 feature-policy 禁用了畫中畫特性,此時 document.pictureInPictureEnabled屬性也會返回 false當前 video 元素通過 disablePictureInPicture 屬性(HTML 屬性和 DOM 屬性均可)禁用了畫中畫特性

2. video 元素新增的屬性 disablePictureInPicture

通過該屬性可以禁用 video 元素的畫中畫特性,右鍵菜單中的“畫中畫”選項會被禁用。

通過 HTML 屬性:

通過 DOM 屬性:

video.disablePictureInPicture = true

3. video 元素新增的事件 enterpictureinpicture 和 leavepictureinpicture

video.addEventListener('enterpictureinpicture', function(pipWindow) { // 進入了畫中畫模式,可以拿到 pipWindow 對象})video.addEventListener('leavepictureinpicture', function() { // 退出了畫中畫模式})

4. document 上新增的方法 exitPictureInPicture()

因為一個頁面只能打開一個 PiP 窗口,所以讓 video 元素退出畫中畫模式的方法不在 video 元素自己身上,而在 document 上。

這個方法也返回一個 promise,不過 promise 包的值是個 undefined。

5. document 上新增的屬性 pictureInPictureElement和 pictureInPictureEnabled

類似於document.pointerLockElement和 document.fullscreenElement, document.pictureInPictureElement 會返回當前頁面中處於畫中畫模式的 video 元素,如果沒有的話,返回 null

document.pictureInPictureEnabled上面已經提到過了,在當前頁面不支持或被禁用畫中畫模式的情況下會返回 false,否則返回 true。

這兩個屬性都是隻讀的。

6. PictureInPictureWindow對象的 API

從requestPictureInPicture()方法的返回值和 enterpictureinpicture事件的回調參數中可以拿到 pipWindow 對象,該對象有兩個屬性 width和height,還支持一個resize事件,在用戶改變 PiP 窗口大小時會觸發。

async function openPiP(video) { const pipWindow = await video.requestPictureInPicture() console.log(pipWindow.width, pipWindow.height) // 打印了默認的窗口大小 pipWindow.addEventListener('resize', function() { console.log(pipWindow.width, pipWindow.height) // 用戶改變 PiP 窗口大小時觸發 })}

注意這裡的 width和height是隻讀的,你不能通過給他們賦值來改變窗口大小。

雜項

1. Safari 中已有的畫中畫 API

Safari 在兩年前就支持了畫中畫模式,還有一套帶前綴的配套 API,叫 Presentation Mode。好消息是這個新規範也有 Safari 的人參與了制定,事實上目前為止四大瀏覽器廠商只剩 Edge 還沒表示支持。

2. 畫中畫這個名字的由來

“畫中畫”這東西是十幾年前電視機上的一個功能,我自己去年看到這個規範的時候也覺的它這個名字比較誤導人,現在規範 issue 裡也有個人在問,希望你沒把它理解成是嵌套的

3. Chrome 哪個版本支持

現在的 Chrome Canary(69)還沒有默認打開這個特性,需要你手動開啟

chrome://flags/#enable-experimental-web-platform-features

chrome://flags/#disable-background-video-track

chrome://flags/#enable-picture-in-picture

這三個開關,不用 Canary 的同學老實等兩個月。

4. 可不可能彈出 video 以外的元素

規範制定者表示未來有可能


分享到:


相關文章: