给任何视频添加画中画按钮
画中画让一个视频在你工作时浮在所有其他窗口之上。浏览器原生支持它,但不少网站把这个按钮从它们的播放器里去掉了。一条 JustZix 规则把它放回每个视频上。
一行代码的 API
任何已加载元数据的 <video> 元素都可以用 video.requestPictureInPicture() 移到一个浮动窗口。它返回一个 promise,而浏览器要求它由一次用户手势(例如点击)触发。
someVideo.requestPictureInPicture().catch(function (err) {
console.warn('PiP refused:', err.message);
});
这就是整个引擎。本文其余部分把它包进一个你可以在任何页面上点击的按钮里。
一个浮动的 PiP 按钮
这条规则注入一个按钮。点击它会找到最大的正在播放的视频并把它弹出。挑选最大的视频可以避免在微小的背景或广告片段上触发。
(function () {
if (!document.pictureInPictureEnabled) { return; }
var btn = document.createElement('button');
btn.textContent = 'PiP';
btn.style.cssText = 'position:fixed;bottom:16px;right:16px;z-index:2147483647;'
+ 'background:#2563eb;color:#fff;border:0;border-radius:8px;'
+ 'padding:8px 14px;font:600 13px sans-serif;cursor:pointer;'
+ 'box-shadow:0 2px 8px rgba(0,0,0,.3)';
document.body.appendChild(btn);
function biggestVideo() {
var best = null, bestArea = 0;
document.querySelectorAll('video').forEach(function (v) {
var r = v.getBoundingClientRect();
var area = r.width * r.height;
if (area > bestArea && v.readyState > 0) {
best = v; bestArea = area;
}
});
return best;
}
btn.addEventListener('click', function () {
if (document.pictureInPictureElement) {
document.exitPictureInPicture();
return;
}
var v = biggestVideo();
if (!v) { return; }
v.requestPictureInPicture().catch(function (err) {
btn.textContent = 'No PiP';
setTimeout(function () { btn.textContent = 'PiP'; }, 1500);
});
});
})();
同一个按钮可切换:如果某个视频已经在 PiP 中,它会调用 exitPictureInPicture()。readyState > 0 检查跳过尚未加载元数据的视频,因为 API 会拒绝那些视频。
双击任何视频把它弹出
如果你不喜欢屏幕上的按钮,就把动作直接绑定到视频上。这条规则让在视频本身上双击来切换 PiP。
document.addEventListener('dblclick', function (e) {
var v = e.target;
if (!v || v.tagName !== 'VIDEO') { return; }
if (!document.pictureInPictureEnabled) { return; }
e.preventDefault();
if (document.pictureInPictureElement === v) {
document.exitPictureInPicture();
} else {
v.requestPictureInPicture().catch(function () {});
}
}, true);
因为监听器使用捕获,它在网站自己的双击处理器之前运行,而 preventDefault() 阻止播放器同时切换全屏。
响应 PiP 事件
你可以通过在视频上监听 enterpictureinpicture 和 leavepictureinpicture 来保持你的 UI 同步:
document.addEventListener('enterpictureinpicture', function (e) {
console.log('floating:', e.target.currentSrc);
}, true);
可靠行为的小技巧
- PiP 需要安全上下文。它在
https页面上有效,在纯http上会被拒绝。 - 如果某个网站在元素上设置了
disablePictureInPicture,先用video.disablePictureInPicture = false清除它。 - 有些单页应用网站在导航时会替换视频元素,所以把按钮规则保持为站点范围生效,而非按页面生效。
从我们的现成示例获取一个打包好的版本,或者下载 JustZix 自己添加。要从一开始就阻止视频自动播放,请阅读停止视频和音频自动播放。
为这篇文章评分
暂无评分 — 成为第一个。