document picture-in-picture仅支持chromium系浏览器(chrome 113+等),且必须由用户手势触发video.requestpictureinpicture(),视频需有有效src、处于安全环境、已播放;状态监听须用document.addeventlistener('enterpictureinpicture')和'leavepictureinpicture',退出应调用document.exitpictureinpicture()。

Document Picture-in-Picture(PiP)目前仅在 Chromium 系统(Chrome 113+、Edge 113+、Opera 99+)中受支持,且必须满足严格条件才能调用 document.pictureInPictureElement 和 document.exitPictureInPicture();它不能用于任意 DOM 元素,仅限于 <video></video> 或 <audio></audio> 元素,并且该媒体元素必须已播放过(即触发过 play 事件或用户手势后自动播放成功)。
如何正确触发进入 PiP 模式
调用 videoElement.requestPictureInPicture() 是唯一入口,但失败非常常见。关键不是“有没有写这行代码”,而是前置状态是否达标:
- 视频必须有
src或通过MediaStream设置了有效媒体源(空src或 404 资源会静默失败) - 页面上下文需为“安全环境”(
https://或localhost),http://非本地域名直接拒绝 - 调用必须由用户手势(如
click、keydown)直接触发,不能包裹在setTimeout或 Promise 回调里 - 若视频设置了
muted且无音轨,部分版本 Chrome 要求显式设置playsinline属性
示例正确写法:
const video = document.querySelector('video');
button.addEventListener('click', async () => {
try {
await video.requestPictureInPicture();
} catch (err) {
console.error('PiP enter failed:', err.name); // 常见:NotAllowedError、SecurityError
}
});
如何监听 PiP 状态变化
不能依赖 videoElement.onenterpictureinpicture 这类事件——它根本不存在。PiP 状态只能通过全局 document 上的两个事件捕获:
-
enterpictureinpicture:触发后document.pictureInPictureElement即为当前 PiP 元素(通常是<video></video>) -
leavepictureinpicture:触发后document.pictureInPictureElement变为null
注意:这两个事件不冒泡,且只在 document 上监听才有效。不要绑定到 video 元素本身。
document.addEventListener('enterpictureinpicture', () => {
console.log('Now in PiP:', document.pictureInPictureElement);
});
document.addEventListener('leavepictureinpicture', () => {
console.log('Left PiP');
});
退出 PiP 的三种方式及兼容性差异
用户可点击 PiP 窗口右上角 × 关闭,也可由脚本控制退出。但退出方式影响行为一致性:
- 调用
document.exitPictureInPicture():最可靠,返回 Promise,可 await 确认退出完成 - 调用
videoElement.exitPictureInPicture():Chrome 117+ 支持,旧版不识别,不推荐 - 直接移除 video 元素或设
src = "":会强制退出 PiP,但可能触发异常或残留 UI,应避免
退出前建议检查状态,防止重复调用报错:
if (document.pictureInPictureElement) {
await document.exitPictureInPicture();
}
PiP 窗口本身不可自定义样式或添加控件,它是浏览器原生浮层;想实现“类 PiP 效果”(如可拖拽、带按钮的浮动面板),得用 CSS + JS 手动模拟,别试图 hack pictureInPictureElement——它只读且无子节点访问权限。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











