requestPictureInPicture()画中画

3,182 阅读3分钟
原文链接: zhuanlan.zhihu.com

新方法requestPictureInPicture()实现画中画(PIP)

画中画就是使视频脱离页面,在新窗口展示的效果。

现在已经有不少画中画效果的应用,例如淘宝的宝贝介绍、各个播放器和广告等,这些基本都是通过对video标签的操作来实现的,讲道理,用canvas也可以实现。本文要说的是一个新的方法requestPictureInPicture(),直接把你的视频“拖”出来。


demo展示:


运行环境:

chrome浏览器:首先要在chrome://flags/下开启以下功能权限

  • Experimental Web Platform features
  • Enable Picture-in-Picture
  • Enable the use of SurfaceLayer objects for videos

如下图:

然后重启浏览器,打开demo地址可查看。

demo:https://codepen.io/wenjing8/full/pQGmJj

最新版的chrome已经默认支持画中画(版本70以后)


主要代码片段:

html

<video id="videoElement" controls="controls" src="//oxyi0vk1f.bkt.clouddn.com/evn4.mp4" class="videoEle"></video>
<button id="pipButtonElement">进入 Picture-in-Picture</button>
<button id="exitPictureInPicture">退出</button>

js

let exitPictureInPicture = document.getElementById("exitPictureInPicture");
let pipButtonElement = document.getElementById("pipButtonElement");
let exitPictureInPicture = document.getElementById("exitPictureInPicture");

//    进入画中画

pipButtonElement.addEventListener('click', async function() {		//change、onload、mousedown
      pipButtonElement.disabled = true;

      try {
	   await videoElement.requestPictureInPicture();
      } catch(error) {
      } finally {
	   pipButtonElement.disabled = false;
      }
  });
    
//    退出画中画

exitPictureInPicture.addEventListener('click',()=>{
      document.exitPictureInPicture();
  })
		
//    监听画中画

videoElement.addEventListener('enterpictureinpicture', (event) => {
        //可获取画中画窗口的一些数据,如宽高等
      pipvideoHeight = event.srcElement.videoHeight;
      pipvideoWidth = event.srcElement.videoWidth;
      console.log("pipvideoHeight:", pipvideoHeight, ",pipvideoWidth:", pipvideoWidth)
  });

videoElement.addEventListener('leavepictureinpicture', (event) => {
      console.log('退出 Picture-in-Picture');
  });

方法解析:

1、浏览器需支持requestPictureInPicture()方法才可实现,可以使用document.pictureInPictureEnabled来进行检测浏览器是否支持
2、进入画中画:video.requestPictureInPicture();
3、退出画中画:document . exitPictureInPicture();
4、禁止画中画:在video标签添加disablePictureInPicture;
5、监听画中画的进入和退出状态:enterpictureinpicture、leavepictureinpicture;监听画中画时可获取画中画窗口的一些数据,如宽高等


结论:

1、现有浏览器默认都不支持requestPictureInPicture()方法,暂时不能运用开发新的功能。

2、requestPictureInPicture()目前仅适用于视频元素在画中画窗口,且一个页面只支持出现一个画中画窗口

3、画中画窗口暂时没有完整的视频控件,只有开始/暂停/关闭三个按钮;画中画窗口始终在屏幕最上层(包括切换页面、应用),且支持拖拽改变位置和尺寸。

4、页面自动执行该方法会被当做恶意行为拦截掉,不出现画中画效果。目前只支持必须是用户手势请求的动作,但是touchstart、touchmove不可以。

  • 自执行事件:html触发mouseover、mousemove、mouseout等事件;js触发click、scroll、onload等事件
  • 用户手势事件:click、dblclick、mousedown、mouseup(点击弹起时)、change、touchend等事件

5、requestPictureInPicture()与window.open、window.showModalDialog()同是弹出新窗口,但有所不同。

  • window.open可通过window.opener与父窗口通信(参考:www.runoob.com/jsref/prop-…
  • window.showModalDialog()可传参控制子窗口,子窗口可通过window.returnValue给父窗口返回信息;(参考:blog.csdn.net/u010033129/…
  • 画中画子窗口和父窗口无通信API,只能监听是否已进入画中画,且requestPictureInPicture()弹出的窗口无导航条,目前可控性还比较弱。


以上为本人调研的结果,如有什么问题,还请大家多多指教。


参考材料:https://wicg.github.io/picture-in-picture/

兼容性:https://caniuse.com/#search=picture-in-picture