浏览器画中画模式
浏览器画中画功能允许用户在一个小的叠加窗口中弹出网页中播放的视频 ?,Chrome 版本大于 71 均默认开启该功能。下面简单介绍一下该 API 如何使用 ?
准备工作
首先要有个 video,以及一个 btn ⏹ 用来 toggle 画中画功能
复制代码
js 部分
js 部分很简单,只需要调用 video 元素的 requestPictureInPicture
方法即可,然后再调用 document 对象下的 exitPictureInPicture
方法就可以关闭画中画功能了 ?
另外,document 对象下的 pictureInPictureElement
指向画中画功能生效的那个 video 元素,如果没有开启画中画,那么返回值是 null
还有就是上述两个 API 都是异步的,始终返回 Promise
const btn = document.querySelector('#toggle')const vid = document.querySelector('#video')async function handleToggle() { try { // 捕获 async-await 错误 ❌ if (vid !== document.pictureInPictureElement) { // 判断当前 PictureInPicture 是否已经开启并是否指向该 video await vid.requestPictureInPicture() // 调用 API 开启功能 ⭕️ } else { await document.exitPictureInPicture() // 调用 API 关闭功能 ⛔️ } this.disabled = true // toggle 按钮避免频繁触发 } catch (error) { // error handler 错误处理 ❌ } finally { this.disabled = false }}btn.addEventListener('click', handleToggle)复制代码
这样就完成了,效果如下:
相关事件
如果需要监听是否开启或关闭画中画功能,可以使用下面两个事件:
vid.addEventListener('enterpictureinpicture', function() { console.warn('on') })vid.addEventListener('leavepictureinpicture', function() { console.warn('off') })复制代码
如果需要监听画中画尺寸 resize 操作:
let pipWindowvid.addEventListener('enterpictureinpicture', function (event) { pipWindow = event.pictureInPictureWindow // 获取当前 pip 窗口 ? console.log(`> Window size is ${pipWindow.width}x${pipWindow.height}`) // width height 属性获得宽高 pipWindow.addEventListener('resize', onPipWindowResize)})vid.addEventListener('leavepictureinpicture', function (event) { pipWindow.removeEventListener('resize', onPipWindowResize)})function onPipWindowResize(event) { console.log(`> Window size changed to ${pipWindow.width}x${pipWindow.height}`) // chrome 建议根据 window 尺寸大小动态调节 video 质量}复制代码
检查是否可用
可能浏览器不支持画中画功能,即便是浏览器支持,可能用户手动关闭或 CFP 的禁止导致无法使用该功能 ?
检查浏览器是否支持:
if (!('pictureInPictureEnabled' in document)) {}
检查是否可用:
if (!document.pictureInPictureEnabled) {}
根据上述判断来动态添加画中画功能按钮:
if ('pictureInPictureEnabled' in document) { // 支持的情况显示按钮 setPipButton() videoElement.addEventListener('loadedmetadata', setPipButton) videoElement.addEventListener('emptied', setPipButton)} else { // 不支持的情况隐藏按钮 pipButtonElement.hidden = true}function setPipButton() { pipButtonElement.disabled = (videoElement.readyState === 0) || !document.pictureInPictureEnabled || videoElement.disablePictureInPicture}复制代码
流媒体的支持
另外画中画功能还支持流媒体。如用户的摄像头、用户屏幕实时共享以及 canvas ?:
摄像头的支持:
const video = document.createElement('video');video.muted = true;video.srcObject = await navigator.mediaDevices.getUserMedia({ video: true });video.play()// Later on, video.requestPictureInPicture();复制代码
屏幕实时共享:
const video = document.createElement('video');video.muted = true;video.srcObject = await navigator.mediaDevices.getDisplayMedia({ video: true });video.play();// Later on, video.requestPictureInPicture();复制代码
canvas:
const canvas = document.createElement('canvas');// Draw something to canvas.canvas.getContext('2d').fillRect(0, 0, canvas.width, canvas.height);const video = document.createElement('video');video.muted = true;video.srcObject = canvas.captureStream();video.play();// Later on, video.requestPictureInPicture();复制代码
获取用户屏幕用到了 screenCapture API
当然这需要用户点击同意才可获得授权
共享过程中会有个 banner 点击停止共享即可停止录制
DEMO 见:
与画中画结合的效果可以看这个 demo: