大家好,我是CC,在这里欢迎大家的到来~
场景
我们在开发工作中经常会使用多个屏幕,多屏操作更加方便快捷;那知道如何在浏览器里进行多屏幕的管理呢?
使用 Web API 的 Window Management API。虽然目前它的兼容性还不是很全,但是未来可期,而且它得使用场景颇为广泛。
- 假如我是一个投资者,每天需要面对很多屏幕来浏览股市涨跌。
- 假如我是一个保安,保卫一方平安,每天要盯着监控录像。
下面进入正文,我们来试试 Window Management API 的效果。
屏幕权限
浏览器安全策略的缘故,当我们想使用浏览器提供的一些 API 时,需要手动授权。
我们现在需要获取的是 window-management 的使用权限。
const permission = await queryWindowManagement();
async function queryWindowManagement() {
// https://developer.mozilla.org/zh-CN/docs/Web/API/Permissions/query
return await navigator.permissions.query({ name: 'window-management' });;
}
if (permission.state === "granted") { // 已经授权
// 执行下一步
} else if (permission.state === "prompt") { // 询问是否授权
// 请求授权
} else if (permission.state === "denied") {
// 权限被拒绝
}
询问是否授权这里目前有一个坑:
有的Web API 自身有请求权限的方法,比如 Notifications API 有方法 requesePermission() ;但是有的没有,比如 Geolocation API。恰巧 Window Management API 也没,悲催。
但是 Permissions API 未来会提供统一的请求权限的方法 Permissions.request() 和 Permissions.requestAll() ,截止文章发布时间这两个方法未有浏览器实现。
所以这里我们只能手动去更改浏览器的权限。
屏幕信息
在获取到屏幕权限后,我们就可以查看屏幕的详细信息了。
但是在这之前,我们需要了解一个概念——多屏原点。
多屏原点
多屏原点——通俗来讲,就是把我们的屏幕放到一个直角坐标系里,原点O(0,0)点就是我们的多屏原点。那哪个位置是原点呢?
我们使用 MDN的例子:1920 x 1080 扩展屏设置为主显示器,1440 x 900 电脑显示器设置为辅助显示器,操作系统 UI 在屏幕顶部占用 25px。
- 当辅助屏幕位于主屏幕右侧,多屏原点就是主显示器的左上角,坐标(0,0)
- 当辅助屏幕位于主屏幕左侧,多屏原点也是主显示器的左上角,坐标(0,0)
ScreenDetailed
继承 Screen 对象,用户可用屏幕设备的属性
- label 屏幕名称
- isPrimary 是否是主屏幕
- isInternal 是电脑自带屏还是外接屏
- top 相对多幕原点顶部距离
- left 相对多幕原点的横向距离
- availTop 可用屏幕区域相对多屏原点的 y 坐标
- availLeft 可用屏幕区域相对多屏原点的 x 坐标
- devicePixelRatio 设备像素比
- isExtended 是否有多个屏幕
Screen
- width 屏宽
- height 屏高
- availWidth 浏览器最大宽度
- availHeight 浏览器最大高度
- pixelDepth 位深度/色彩深度
- colorDepth 颜色深度
- orientation 屏幕当前方向
以上属性我们在哪里能看到呢?通过 window.getScreenDetails() 方法返回一个 ScreenDetails 对象,包含 currentScreen 当前屏幕的属性和 screens 所有可用屏幕的属性。
let screens = [];
let currentScreen = null;
let screenDetails = null;
screenDetails = await window.getScreenDetails();
currentScreen = screenDetails.currentScreen;
screens.push(...screenDetails.screens);
投送屏幕
屏幕投送就是把某个内容的浏览器放到某个屏幕上。
有两种方式:
一是通过在某个坐标点打开新的浏览器窗口或者标签页,二者可以把当前浏览器移动到屏幕上。
打开
function delivery (screen, url) {
const {top, left, width, height} = screen;
const features = [
`left=${left}`,
`top=${top}`,
`width=${width}`,
`height=${height}`,
`menubar=no`,
`toolbar=no`,
`location=no`,
`status=no`,
`resizable=yes`,
`scrollbars=no`
].join(",");
return window.open(url, Math.random().toString(), features);
}
注意:在 Mac 笔记本上如果当前浏览器处于全屏状态,window.open 会打开一个标签页,而如果当前浏览器未处于全屏状态下的话 window.open 会重新打开新的浏览器窗口。
移动
function move(top, left) {
window.moveTo(top, left);
}
全屏
屏幕全屏可以控制把某个 DOM 全屏以及全屏放置到哪个屏幕上。
async function toggleFullscreen(screenId) {
await toggleElementFullscreen(document.body, screenId);
}
async function toggleElementFullscreen(element, screenId) {
if (Number.isInteger(screenId) && screenId >= 0 && screenId < screens.length) {
// 选择在对应屏幕上全屏展示
await element.requestFullscreen({ screen: screens[screenId] });
} else if (document.fullscreenElement == element) {
// 如果已经全屏则退出全屏
await document.exitFullscreen();
} else {
// 默认在当前屏幕全屏
await element.requestFullscreen();
}
}
监听屏幕变化
change()
change 事件是 Screen 对象上的,只有 Screen 上一个或多个属性发生改变时就会触发特定屏幕上的 change 事件。
const firstScreen = (await window.getScreenDetails()).screens[0];
firstScreen.addEventListener("change", (event) => {
console.log("The first screen has changed.", event, firstScreen);
});
currentscreenchange()
currentscreenchange 事件属于 ScreenDetails 对象,触发事件的行为有以下几个:
-
当前浏览器窗口被移动到其他屏幕上
-
Screen 对象的一个或多个属性值发生变化
-
ScreenDetails 对象的以下一个或多个属性值发生变化
- isPrimary
- isInternal
- top
- left
- availTop
- availLeft
- devicePixelRatio
const screenDetails = await window.getScreenDetails();
screenDetails.addEventListener("currentscreenchange", (event) => {
const details = screenDetails.currentScreen;
console.log("The current screen has changed.", event, details);
});
screenchange()
screenchange 事件也属于 ScreenDetails 对象,当系统可用的屏幕集发生变化时,像有新屏幕可用或现有屏幕不可用,比如拔掉扩展屏的 HDMI 连线就是现有屏幕不可用。
当触发 screenchange 事件时,我们就能监测到什么时候可用屏幕发生了更改,然后上报更改,关闭所有的浏览器窗口,最后重新打开所有窗口来适应新的屏幕配置。
const screenDetails = await window.getScreenDetails();
let noOfScreens = screenDetails.screens.length;
screenDetails.addEventListener("screenschange", () => {
if (screenDetails.screens.length !== noOfScreens) {
console.log(
`The screen count changed from ${noOfScreens} to ${screenDetails.screens.length}`,
);
noOfScreens = screenDetails.screens.length;
}
updateWindows();
});
更多有趣的 Demo
参考资料
developer.mozilla.org/en-US/docs/…
developer.mozilla.org/en-US/docs/…
API 兼容性目前还需要再等等!