浏览器的多屏协作

最近收到个需求,需要将收费项目展示给用户看,肯定不能将系统工作台面向用户吧,所以只能将需要展示的数据传输到扩展屏中,给用户看。有点类似餐厅中前后屏的意思。

基本思路

  1. 浏览器打开一个页面
  2. 传输数据到另一个页面中
  3. 接收数据并展示

梳理功能

  1. chrome100+ 有新api, window.getScreenDetails() 可以获取当前系统的屏幕信息,当然获取之前需要请求权限:navigator.permissions.query({ name: 'window-management' }) 这也决定了只能谷歌浏览器 其他不行。其他浏览器因为找不到扩展屏的位置,只能在本窗口打开了。
    如果满足条件,window.getScreenDetails()会返回下面的数据,我们可以找到isPrimary为false的屏幕,然后得到这块屏幕的位置。
screens: [{
availHeight: 816
availLeft: 0
availTop: 0
availWidth: 1536
colorDepth: 24
devicePixelRatio: 1.25
height: 864
isExtended: true
isInternal: true
isPrimary: true  //是否是主屏幕
label: ""
left: 0
onchange: null
orientation: {angle: 0, type: 'landscape-primary', onchange: null}
pixelDepth: 24
top: 0
width: 1536
}]
  1. 打开页面 我们都知道有window.open(url, target, feature) MDN文档 我们常用的肯定是前两个参数,第三个参数就是打开的这个页面需要展示在哪个位置(left,top, width,height,这几个参数就是需要1中得到的扩展屏的信息)和页面的一些配置。
    这个配置中有一个参数 “noopener ”,文档说加这个参数 新窗口会拿不到旧窗口的引用,属于安全机制,但是实测发现 旧窗口也拿不到新窗口的引用了。也就是无法使用window.postMessage进行通讯了。
    如果不介意安全,可以去掉noopener 直接使用window.open()返回的窗口引用来通讯。
  2. 如果比较介意安全机制,就使用BroadcastChannel来通讯。这个api几乎现代浏览器都支持。
channel = new BroadcastChannel('pay-channel')
channel.postMessage({
    //自定义对象
    type: type,
    data: data
})
  1. 新窗口设计
    首先 url肯定也属于我们的项目页面,即使没有通过router.push打开,也需要将页面加入路由。
    页面接收数据的方法,与旧窗口一样,必须保证'pay-channel',这个字符串要一样才可以通信
let channel = new BroadcastChannel('pay-channel')
channel.onmessage(message, (event) => {
    //得到的数据展示在页面即可
}
  1. tips
    在与新窗口通讯时,如果在新窗口刚打开 立马postMessage,新窗口会接收不到数据,因为页面还未初始化完成,所以需要延时,我实测至少需要延时1.5s

总结

经过上面的步骤 我们在谷歌浏览器已经实现了将窗口弹出到扩展屏的功能。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容