目前有越来越多的开发者外接多个显示器进行工作,但是有没有发现你在浏览器中打开新窗口时,都只会显示在你当前的显示屏里,如果想放置在某个浏览器中,需要把窗口拖过去,有没有可能直接在指定的显示屏中打开窗口呢?
通常我们可以通过 window.open 方式来打开一个窗口,如:
const popup = window.open(
"https://www.baidu.com/",
"_blank",
"width=400, height=300, left=100, top=100"
);
但是都只是在当前屏幕上打开的,如何能让其在指定的显示屏中打开窗口呢?
01
Multi-Screen Window Placement API
从Chrome 86起,开始支持Multi-Screen Window Placement API了,不过还处于试验阶段,可以在 chrome://flags 里开启 #enable-experimental-web-platform-features
判断浏览器是否支持该特性
if ("getScreens" in window) {
//支持
}
判断是否接入多个显示屏
await isMultiScreen()
请求权限
const permission = await navigator.permissions.query({
name: 'window-placement'
});
getScreens()方法
await window.getScreens();
事件监听
window.addEventListener('screenschange', () => {
//
});
全屏
requestFullscreen也相应增加了screen配置项
***.requestFullscreen({
screen: screen[0]
})
02
演示效果
下面视频演示分别点击页面上的3个按钮,会分别在对应的显示屏中打开一个小窗口。
03
代码示例
css、html
<style>
#demo{width: 600px;}
#demo .warning {font-size: 14px; color: #f00}
#demo .buttons input[type="button"] {height: 40px; font-size: 15px; margin-right: 20px; color: #fff; background: #389e88; border: 0; border-radius: 5px;}
#demo .buttons input[type="button"]:active {background: rgb(10, 233, 10)}
#demo .screens {margin-top: 10px}
#demo .screens dl {background: #ccc; font-size: 13px; line-height: 20px; margin-top: 10px; padding: 10px}
#demo .screens dt {font-size: 16px; font-weight: bold; color: #1d3bd2; margin-bottom: 10px}
#demo .screens dd {padding: 0; margin: 0;}
</style>
<div id="demo">
<strong class="warning"></strong>
<div class="buttons"></div>
<div class="screens"></div>
</div>
js
class MultiScreen {
constructor() {
const _this = this;
_this.screens = [];
_this.init();
}
async init() {
const _this = this;
if (!('getScreens' in self)) {
alert('你的chrome版本不支持该功能!');
} else if ('isMultiScreen' in self && !(await isMultiScreen())) {
alert('请接入多个显示屏查看该demo!');
} else {
const permission = await navigator.permissions.query({
name: 'window-placement'
});
permission.addEventListener('change', () => {
_this.updateScreensInfo();
});
if ('onscreenschange' in self) {
window.addEventListener('screenschange', () => {
_this.updateScreensInfo();
});
_this.updateScreensInfo();
}
}
}
async getScreensData() {
const _this = this;
_this.screens = (await getScreens().catch(_ => {})) || [window.screen];
}
async updateScreensInfo() {
const _this = this;
let buttons = [];
let screens = [];
await _this.getScreensData();
const permission = await navigator.permissions.query({
name: 'window-placement'
});
if (permission.state === 'denied') {
document.querySelector('#demo .warning').innerHTML = '您禁用了窗口放置权限,请开启使用';
}
_this.screens.forEach((item, index) => {
buttons.push(`
<input type="button" value="在第 ${index + 1} 个显示屏中打开" data-index="${index + 1}">
`);
screens.push(`
<dl>
<dt>screen ${index + 1} :</dt>
<dd>
id: ${item.id}<br>
width: ${item.width}<br>
height: ${item.height}<br>
availWidth: ${item.availWidth}<br>
availHeight: ${item.availHeight}<br>
left: ${item.left}<br>
top: ${item.top}<br>
primary: ${item.primary}<br>
internal: ${item.internal}<br>
touchSupport: ${item.touchSupport}<br>
</dd>
</dl>
`);
});
document.querySelector('#demo .buttons').innerHTML = buttons.join('');
document.querySelector('#demo .screens').innerHTML = screens.join('');
document.querySelectorAll('#demo input[type="button"]').forEach((item, index) => {
item.addEventListener('click', () => _this.openWin(index, screens[index]));
});
}
openWin(index, html) {
const _this = this;
const screen = _this.screens[index];
const optionsStr = `
width=400,
height=300,
left=${screen.availLeft + (screen.availWidth / 2) - 200},
top=${screen.availTop + (screen.availHeight / 2) - 150}
`;
const win = window.open('about:blank', '_blank', optionsStr);
win.document.write(html);
}
}
new MultiScreen();
04
screen数据
以下是部分screen数据:
其中 primary 表示是否是主显示屏,internal 表示是否是内置显示屏。
id: 0
width: 1280
height: 800
availWidth: 1280
availHeight: 734
left: 0
top: 0
primary: true
internal: true
touchSupport: false
id: 1
width: 1920
height: 1200
availWidth: 1920
availHeight: 1177
left: 0
top: -1200
primary: false
internal: false
touchSupport: false
05
应用场景
可能有人会觉得这个功能意义不大,但是我觉得一方面可以提升交互体验,另一方面,随着多屏、折叠屏等设备越来越多,跨屏交互势必会被重视,(如折叠屏就已经有了相关css与js api: @media (spanning: single-fold-vertical), window.getWindowSegments()),可以提前掌握并进行一些技术创新。
目前我能想到的几个应用场景:
1、股市行情展示
同时在多个屏幕上打开并排列不同的股市行情窗口。
2、数据可视化大屏展示
目前的数据可视化大屏展示基本都是整合在一个页面中的,如果需要调整结构布局,可能就需要修改代码,如果开发时考虑好让每个模块可以独立展示,那么就可以借助这个功能,设定好布局后,就可以一键窗口排列展示。
3、在线ppt演示
目前市场上有很多在线版的ppt,提供了演讲者模式,一个窗口是用来在投影仪上展示的,另一个是用来在笔记本屏幕上显示演讲者笔记,但是目前使用时就需要手动去调整窗口到不同的屏幕上,现在我们是否可以这样去优化提升体验,点击 “演讲者模式” 按钮后,直接一个窗口全屏展示在投影仪,另一个演讲者笔记窗口保留在笔记本屏幕上。
4、简单的小游戏多屏布局
...
06
一点设想
目前要在不同屏幕上打开窗口,主要还是通过 js 的window.open去实现,以后能不能直接在 <a> 标签的_target上增加一项呢,指定在哪个显示屏上打开,如:
<a href="https://www.so.com/" _target="screen[0]">...</a>
以及 window.open 第二个参数是不是也可以考虑支持呢?
07
Chrome扩展
在此顺便推广一下我以前开发的一个chrome扩展 “多显示窗口管理” :
详细介绍见另一个文章:Chrome插件分享:多显示器窗口管理
该扩展支持在多个显示器之间进行窗口切换、最大化、居中、贴边、垂直/水平排列、标签页从窗口分离/合并、以及快捷键支持。
1. 窗口可以在多个显示器之间快速移动,而无需拖动;
2. 窗口最大化、居中、贴边;
3. 窗口1x2、2x1、2x2排列;
4. 窗口标签页从窗口分离、合并;
默认支持以下快捷键:
1. 在多个显示器之间切换(windows: ctrl+→,Mac: ⌘+→)
2. 调整窗口大小且循环切换(windows: ctrl+↑,Mac: ⌘+↑)
3. 窗口依次在屏幕左、上、右、下贴边切换(windows: ctrl+←,Mac: ⌘+←)
其他快捷键可自定义设置。
end