随着2016年macOS Sierra的发布,画中画在Safari浏览器中首次出现在网络上。它使用户可以将视频弹出到一个小的浮动窗口中,该窗口始终位于其他窗口之上,这样他们就可以在做其他事情时继续观看视频。这个想法来自于电视,例如,当你在浏览指南甚至其他频道时,你可能想继续观看热门体育赛事。

不久之后,安卓8.0发布了,它通过本地API提供了对画中画的支持。安卓版的chrome能够通过这个API以画中画的模式播放视频,尽管它的桌面版无法做到这一点。

这导致起草了一个画中画Web API的标准,使得网站有可能发起和控制这种行为。

在写这篇文章的时候,只有Chrome(70+版本)和Edge(76+版本)支持这个新特性。Firefox,Safari和Opera均使用专用的API进行实现。

这份浏览器支持数据来自Caniuse,它包含了更多信息。数字表示浏览器支持这个功能的版本及更高版本。

image.png

如何使用Picture-In-Picture API

让我们通过将视频添加到网页开始。

  1. <video controls src="video.mp4"></video>

在Chrome浏览器中,将会存在一个用于进入和退出画中画模式的开关。
image.png

要测试Firefox的实现,你需要先在about:config中启用media.videocontrols.picture-in-picture.enabled标志,然后右键单击视频以找到画中画选项。
image.png
Firefox开启画中画模式视频

虽然这是可行的,但在许多情况下,你希望你的视频控件在各个浏览器中保持一致,并且可能希望控制哪些视频可以输入画中画模式,哪些不能。

我们可以使用我们自己的方法,用picture-in-picture Web API来替代在浏览器中进入画中画模式的默认方法。例如,让我们添加一个按钮,当点击时,启用它:

  1. <button id="pipButton" class="hidden" disabled>Enter Picture-in-Picture mode</button>

然后在JavaScript中选中视频和按钮:

  1. const video = document.getElementById('video');
  2. const pipButton = document.getElementById('pipButton');

默认情况下,该按钮是隐藏和禁用的,因为在显示按钮之前,我们需要知道用户的浏览器是否支持并启用了画中画API。这是一种渐进增强的形式,有助于避免在不支持该特性的浏览器中出现不良的体验。

我们可以检查API是否受支持,并启用按钮,如下所示:

if ('pictureInPictureEnabled' in document) {
  pipButton.classList.remove('hidden')
  pipButton.disabled = false;
}

进入画中画模式

假设我们的 JavaScript 已经确定浏览器启用了对画中画的支持。单击带有#pipButton的按钮时,让我们调用视频元素的requestPictureInPicture()方法。此方法返回一个promise,当状态变为resolved后,在默认情况下,会将视频放置在屏幕右下角的迷你窗口中,尽管用户可以移动它。

if ('pictureInPictureEnabled' in document) {
  pipButton.classList.remove('hidden')
  pipButton.disabled = false;

  pipButton.addEventListener('click', () => {
    video.requestPictureInPicture();
  });
}

我们无法按原样保留上面的代码,因为requestPictureInPicture()返回一个promise,并且这个promise有可能会拒绝,例如,如果尚未加载视频元数据或视频上存在disablePictureInPicture属性。

让我们添加一个catch块来捕获此潜在错误,并让用户知道发生了什么:

pipButton.addEventListener('click', () => {
  video
    .requestPictureInPicture()
    .catch(error => {
      // Error handling
    });
});

退出画中画模式

浏览器在图片中的窗口上提供了一个关闭按钮,使窗口在点击时能够关闭。不过,我们还可以提供另一种退出画中画模式的方法。例如,我们可以让单击我们的#pipButton时关闭任何活动的画中画窗口。

pipButton.addEventListener('click', () => {
  if (document.pictureInPictureElement) {
    document
      .exitPictureInPicture()
      .catch(error => {
      // Error handling
    })
  } else {
    // Request Picture-in-Picture
  }
});

你可能要关闭画中画窗口的另一种情况是视频进入全屏模式时。 Chrome已经自动执行此操作,而无需编写任何代码。

画中画事件

浏览器使我们能够检测视频何时进入或离开画中画模式。由于可以进入或退出画中画模式,因此最好依靠事件检测来更新媒体控件。

事件分别为enterpictureinpictureleavepictureinpicture,顾名思义,当视频进入或退出画中画模式时,这两个事件将触发。

在我们的示例中,我们需要根据视频当前是否处于画中画模式来更新#pipButton标签。
以下代码可帮助我们实现这一它:

video.addEventListener('enterpictureinpicture', () => {
  pipButton.textContent = 'Exit Picture-in-Picture mode';
});

video.addEventListener('leavepictureinpicture', () => {
  pipButton.textContent = 'Enter Picture-in-Picture mode';
});

这里有一个demo

自定义画中画窗口

默认情况下,浏览器在画中画窗口中显示“播放/暂停”按钮,除非视频正在播放MediaStream对象(例如由相机、视频记录设备、屏幕共享服务或其他硬件产生的虚拟视频源)。

也可以添加直接从画中画窗口转到上一曲目或下一曲目的控件:

navigator.mediaSession.setActionHandler('previoustrack', () => {
  // Go to previous track
});

navigator.mediaSession.setActionHandler('nexttrack', () => {
  // Go to next track
});

在画中画窗口中显示网络摄像头

当用户在应用程序和其他浏览器选项卡或窗口之间来回切换时,将视频会议Web应用程序设置为画中画模式可受益于此。
这里有一个demo

在视频中禁用画中画

<video disablePictureInPicture controls src="video.mp4>"></video>

结束

这就是现在你需要了解的关于画中画Web API的所有内容!目前,该API只支持<video>元素,但它也可以扩展到其他元素。
尽管目前浏览器对它的支持很少,但是你仍然可以使用它来逐步增强网站上的视频体验。

进一步阅读

原文链接:https://css-tricks.com/an-introduction-to-the-picture-in-picture-web-api/