Chrome 震撼新特性:文档画中画!(不光是视频)

共 14705字,需浏览 30分钟

 ·

2023-07-12 18:24






Anthony Fu 大佬分享了一个让人亢奋的消息!


Google Chrome 推出了文档画中画(不光是视频)的一系列支持。


c691bebf470eda2e9dc1e7b8f8540389.webp

咱们通过 Gif 来看一下:


fe948be81f5eb2d36901d2c79fc55b17.webp

简单来说,就是把一个网页中 Nuxt Devtool 那一小部分的元素,直接用画中画的方式剥离到了置顶的小窗口中展示。这也太实用了,以前只有 video 元素可以这样做,这个新功能给了 Web 内容更无边的想象空间!


文档画中画(Document Picture-in-Picture)API[1]现在可以在弹出置顶的小窗口中展示任意 HTML 内容。它扩展了现有的视频画中画(Picture-in-Picture)API[2],后者仅允许将 HTML 的video元素放入画中画窗口中。


谷歌针对这个特性,发布了一个详细的文档Picture-in-Picture for any Element, not just video[3],接下来就由我来给大家分享一下:


Picture-in-Picture for any Element

文档画中画 API 中的画中画窗口类似于通过`window.open()`[4]打开的空白同源窗口,但存在一些区别:



  • 画中画窗口浮动在其他窗口之上。


  • 画中画窗口不会超过打开它的窗口的生命周期。


  • 无法导航画中画窗口。


  • 网站无法设置画中画窗口的位置。

ebf5b93dcec75820ef139e894027cb89.webp

使用文档画中画 API 创建的画中画窗口(示例[5])。



当前状态














步骤 状态
1. 创建说明文档
完成
[6]
2. 创建规范初始草案
进行中
[7]
3. 收集反馈并迭代设计
进行中
[8]
4. 原型试验
已开始
[9]
5. 发布 未开始


在桌面上尝试 API


在试用阶段,你可以通过以下两种方法在桌面上测试这个 API。



本地测试


要在本地尝试文档画中画 API,无需原型试验 Token,只需启用chrome://flags/#document-picture-in-picture-api标志。



注册原型试验


从 Chrome 111 版本开始,文档画中画 API 可以作为原型试验[10]使用。预计该试验将于 Chrome 115 版本(2023 年 9 月 8 日)结束。在此注册[11]。



应用场景



自定义视频播放器


网站可以利用现有的video 画中画 API[12]提供画中画视频体验,但其功能非常有限。现有的画中画窗口接受的输入较少,并且在样式方面的能力也有限。通过完整的画中画文档,网站可以提供自定义的控件和输入选项(例如字幕[13]、播放列表、时间轴、视频点赞和踩),来改善用户的画中画视频体验。



视频会议


在视频会议期间,用户通常出于各种原因(例如展示另一个选项卡以进行通话或多任务处理)而离开浏览器标签,但仍希望保持通话的可见性,因此这是画中画的一个主要应用场景。再次强调,当前视频会议网站通过video 画中画 API[14]提供的体验在样式和输入方面有限。通过完整的画中画文档,网站可以轻松将多个视频流合并到单个画中画窗口中,而无需依赖Canvas 技巧[15],并提供自定义控件,例如发送消息、静音其他用户或举手等功能。



提高生产力


研究表明,用户需要更多在网络上提高生产力的方式。画中画中的文档使 Web 应用程序具备了更大的灵活性来完成更多任务。无论是文本编辑、记笔记、任务列表、消息和聊天,还是设计和开发工具,Web 应用程序现在都可以始终保持内容的可访问性。



接口



属性



documentPictureInPicture.window


返回当前的画中画窗口(如果有)。否则,返回null



方法



documentPictureInPicture.requestWindow(options)


返回一个 Promise,在打开画中画窗口时解析。如果在用户没有进行操作的情况下调用该方法,Promise 将被拒绝。options字段包含以下可选成员:



width


设置画中画窗口的初始宽度。



height


设置画中画窗口的初始高度。



事件



documentPictureInPicture.onenter


在打开画中画窗口时,在documentPictureInPicture上触发。



示例


以下 HTML 代码设置了一个自定义视频播放器和一个按钮元素,用于在画中画窗口中打开视频播放器。





<div id=
"playerContainer"
>

  <div id=
"player"
>

    <video id=
"video"
></video>

  </div>

</div>

<button id=
"pipButton"
>打开画中画窗口</button>




打开画中画窗口


以下 JavaScript 代码在用户点击按钮时调用documentPictureInPicture.requestWindow(),以打开一个空白的画中画窗口。返回的 Promise 将解析为一个画中画窗口的 JavaScript 对象。使用append\(\)[16]方法将视频播放器移动到该窗口中。





pipButton.addEventListener(
"click"
, async () => {

  const player = document.querySelector(
"#player"
);


  // 打开一个画中画窗口。

  const pipWindow = await documentPictureInPicture.requestWindow();


  // 将播放器移动到画中画窗口中。

  pipWindow.document.body.append(player);

});




设置画中画窗口的大小


要设置画中画窗口的大小,请将documentPictureInPicture.requestWindow()widthheight选项设置为所需的画中画窗口大小。如果选项值太大或太小,无法适应用户友好的窗口大小,Chrome 可能会截断展示它们。





pipButton.addEventListener(
"click"
, async () => {

  const player = document.querySelector(
"#player"
);


  // 打开一个与播放器大小相同的画中画窗口。

  const pipWindow = await documentPictureInPicture.requestWindow({

    width: player.clientWidth,

    height: player.clientHeight,

  });


  // 将播放器移动到画中画窗口中。

  pipWindow.document.body.append(player);

});




将样式表复制到画中画窗口


要从原始窗口复制所有 CSS 样式表,请循环遍历初始文档的styleSheets[17],把它们添加到画中画窗口中。请注意,这是个一次性的复制。





pipButton.addEventListener(
"click"
, async () => {

  const player = document.querySelector(
"#player"
);


  // 打开一个画中画窗口。

  const pipWindow = await documentPictureInPicture.requestWindow();


  // 从初始文档中复制样式表,以使播放器外观相同。

  const allCSS = [...document.styleSheets]

    .map((styleSheet) => {

      try {

        
return
 [...styleSheet.cssRules].map((r) => r.cssText).join(
""
);

      } catch (e) {

        const link = document.createElement(
"link"
);

        link.rel = 
"stylesheet"
;

        link.type = styleSheet.type;

        link.media = styleSheet.media;

        link.href = styleSheet.href;

        pipWindow.document.head.appendChild(link);

      }

    })

    .filter(Boolean)

    .join(
"\n"
);

  const style = document.createElement(
"style"
);

  style.textContent = allCSS;

  pipWindow.document.head.appendChild(style);


  // 将播放器移动到画中画窗口中。

  pipWindow.document.body.append(player);

});



copyStyleSheets选项在先前版本的规范中得到支持。现在弃用了(详情请参阅GitHub Pull Request[18])。



处理画中画窗口关闭时的情况


通过监听窗口的"pagehide"事件,可以了解画中画窗口何时关闭(无论是因为网站启动还是用户手动关闭)。Evnet 事件可以很方便的知晓用户何时从画中画返回,如下所示:





pipButton.addEventListener(
"click"
, async () => {

  const player = document.querySelector(
"#player"
);


  // 打开一个画中画窗口。

  const pipWindow = await documentPictureInPicture.requestWindow();


  // 将播放器移动到画中画窗口中。

  pipWindow.document.body.append(player);


  // 当画中画窗口关闭时,将播放器移回原位置。

  pipWindow.addEventListener(
"pagehide"
, (event) => {

    const playerContainer = document.querySelector(
"#playerContainer"
);

    const pipPlayer = event.target.querySelector(
"#player"
);

    playerContainer.append(pipPlayer);

  });

});



使用`close()`[19]方法以编程方式关闭画中画窗口。





// 以编程方式关闭画中画窗口。

// 
"pagehide"
事件将正常触发。

pipWindow.close();




监听网站进入画中画模式


监听documentPictureInPicture"enter"事件,可以知道用户何时打开画中画窗口。事件包含一个window对象,可用于访问画中画窗口。





documentPictureInPicture.addEventListener(
"enter"
, (event) => {

  const pipWindow = event.window;

});




访问画中画窗口中的元素


要访问画中画窗口中的元素,可以使用documentPictureInPicture.requestWindow()返回的对象,或者如下所示使用documentPictureInPicture.window





const pipWindow = documentPictureInPicture.window;

if
 (pipWindow) {

  // 静音在画中画窗口中播放的视频。

  const pipVideo = pipWindow.document.querySelector(
"#video"
);

  pipVideo.muted = 
true
;

}




处理来自画中画窗口的事件


像通常在 JavaScript 中那样,创建按钮和控件,并响应用户的输入事件,如"click"





// 向画中画窗口添加
"mute"
按钮。

const pipMuteButton = pipWindow.document.createElement(
"button"
);

pipMuteButton.textContent = 
"Mute"
;

pipMuteButton.addEventListener(
"click"
, () => {

  const pipVideo = pipWindow.document.querySelector(
"#video"
);

  pipVideo.muted = 
true
;

});

pipWindow.document.body.append(pipMuteButton);




特性检测


要检查是否支持文档画中画 API,请使用:






if
 (
"documentPictureInPicture"
 
in
 window) {

  // 支持文档画中画API。

}




演示



VideoJS 播放器


你可以使用文档画中画 API 的VideoJS 播放器演示[20]进行尝试。欢迎查看源代码[21]。



番茄钟


Tomodoro[22],一个番茄钟网络应用程序,在可用时也利用了文档画中画 API(请参阅GitHub Pull Request[23])。


d798ed7844112086efbd1481f559e25f.webp番茄时钟 Tomodoro


反馈


在这个阶段,开发者的反馈非常重要,请在 GitHub 上提交问题[24],提出建议和问题。



学习资料



  • 公开说明
    [25]


  • WICG 规范
    [26]


  • Chromium 跟踪问题
    [27]


  • ChromeStatus.com 条目
    [28]


  • Blink 组件:\`Blink>Media>PictureInPicture\`[29]


  • TAG Review
    [30]


  • Intent to Experiment
    [31]



参考资料


向下滑动查看







[1]


文档画中画(Document Picture-in-Picture)API: https://wicg.github.io/document-picture-in-picture/



[2]

视频画中画(Picture-in-Picture)API: https://developer.chrome.com/blog/watch-video-using-picture-in-picture/




[3]

Picture-in-Picture for any Element, not just video: https://developer.chrome.com/docs/web-platform/document-picture-in-picture/




[4]

undefined: undefined




[5]

示例: https://document-picture-in-picture-api.glitch.me/




[6]

完成: https://github.com/WICG/document-picture-in-picture/blob/main/README.md




[7]

进行中: https://wicg.github.io/document-picture-in-picture/




[8]

undefined: undefined




[9]

已开始: https://developer.chrome.com/origintrials/#/view_trial/1885882343961395201




[10]

原型试验: https://developer.chrome.com/docs/web-platform/origin-trials/




[11]

在此注册: https://developer.chrome.com/origintrials/#/view_trial/1885882343961395201




[12]

video 画中画 API: https://developer.chrome.com/blog/watch-video-using-picture-in-picture/




[13]

字幕: https://bugs.chromium.org/p/chromium/issues/detail?id=854935




[14]

video 画中画 API: https://developer.chrome.com/blog/watch-video-using-picture-in-picture/




[15]

Canvas 技巧: https://developer.chrome.com/blog/watch-video-using-picture-in-picture/#show-canvas-element-in-picture-in-picture-window




[16]

append(): https://developer.mozilla.org/docs/Web/API/Element/append




[17]

styleSheets: https://developer.mozilla.org/docs/Web/API/Document/styleSheets




[18]

GitHub Pull Request: https://github.com/WICG/document-picture-in-picture/pull/79




[19]

undefined: undefined




[20]

VideoJS 播放器演示: https://document-picture-in-picture-api.glitch.me/




[21]

源代码: https://glitch.com/edit/#!/document-picture-in-picture-api?path=script.js




[22]

Tomodoro: https://lazy-guy.github.io/tomodoro/index.html




[23]

GitHub Pull Request: https://github.com/lazy-guy/tomodoro/pull/2




[24]

提交问题: https://github.com/WICG/document-picture-in-picture/issues




[25]

公开说明: https://github.com/WICG/document-picture-in-picture/blob/main/README.md




[26]

WICG 规范: https://wicg.github.io/document-picture-in-picture/




[27]

Chromium 跟踪问题: https://bugs.chromium.org/p/chromium/issues/detail?id=1315352




[28]

ChromeStatus.com 条目: https://chromestatus.com/feature/5755179560337408




[29]

undefined: undefined




[30]

TAG Review: https://github.com/w3ctag/design-reviews/issues/798




[31]

Intent to Experiment: https://groups.google.com/a/chromium.org/g/blink-dev/c/Tz1gUh92dXs










- EOF -







2be0d25f865a1d0773422d0c169216de.webp


加主页君微信,不仅前端技能+1


3d65b45cb9dc5defc4529ae5189d4ae7.webp4773da03e86039257bfd0f9daf27caa7.webp

主页君日常还会在个人微信分享前端开发学习资源技术文章精选,不定期分享一些有意思的活动岗位内推以及如何用技术做业余项目





加个微信,打开一扇窗









推荐阅读  点击标题可跳转


1、如何在 Axios 中去控制 Loading?大有学问!



2、在高德地图实现自动巡航



3、JavaScript 奇技淫巧:debugger 拦截







觉得本文对你有帮助?请分享给更多人




推荐关注「前端大全」,提升前端技能




点赞和在看就是最大的支持
❤️



浏览 98
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报