在标题栏中显示内容
PWA 可以使用 Web 应用清单文件中的显示成员来定义在移动平台上的 显示 方式。 但是,若要创建类似于本机的沉浸式体验, 桌面 PWA 可以使用另一种方法。
默认情况下,安装在桌面上的 PWA 可以在紧邻保留标题栏区域下方的区域中显示内容:
显示标题栏通常所在的内容可以帮助 PWA 感觉更原生。 许多桌面应用程序(例如Visual Studio Code、Microsoft Teams 和 Microsoft Edge)都已执行此操作:
窗口控件覆盖 API 执行以下操作:
- 允许在应用的整个外围应用上显示 Web 内容。
- 将系统所需的关键窗口控件移动到覆盖层中。
- 使内容能够远离此覆盖。
在应用中启用窗口控件覆盖
首先,在应用的 Web 应用清单文件中启用窗口控件覆盖功能。 为此,请在清单文件中设置 display_override
属性:
{
"display_override": ["window-controls-overlay"]
}
切换标题栏
启用“窗口控件覆盖”功能后,用户可以通过单击标题栏切换按钮来选择是否拥有标题栏:
代码不能假定窗口控件覆盖已显示,因为:
- 用户可以选择是否显示标题栏。
- 你的应用还可以在 Web 浏览器或移动设备中运行,以及作为桌面应用运行。
因此,代码需要对标题栏几何图形更改做出反应。 若要了解详细信息,请参阅覆盖更改React。
使用 CSS 环境变量来清除覆盖层
env()
CSS 函数可用于访问用户代理定义的环境变量。
窗口控件覆盖功能添加了四个环境变量:
变量 | 说明 |
---|---|
titlebar-area-x |
通常由标题栏从窗口左侧占用的区域的距离(以 为单位 px ) |
titlebar-area-y |
通常由标题栏从窗口顶部占用的区域的距离(以 为单位 px ) |
titlebar-area-width |
标题栏区域的宽度,in px |
titlebar-area-height |
标题栏区域的高度,in px |
当禁用窗口控件覆盖功能时,可以使用这些环境变量来定位和调整自己的内容(通常显示标题栏的位置):
#title-bar {
position: fixed;
left: env(titlebar-area-x, 0);
top: env(titlebar-area-y, 0);
height: env(titlebar-area-height, 50px);
width: env(titlebar-area-width, 100%);
}
使用 position: fixed;
可确保标题栏不会随其余内容滚动,而是与窗口控件覆盖保持一致。
了解覆盖层的位置及其有多大非常重要。 覆盖层可能并不总是位于窗口的同一侧;在 macOS 上,覆盖层位于左侧,但在 Windows 上,覆盖层位于右侧。 此外,覆盖层可能并不总是相同的大小。
env()
CSS 函数采用第二个参数,当缺少或禁用窗口控件覆盖功能时,该参数可用于定义应用内容的位置。
为窗口创建应用区域拖动处理程序
隐藏标题栏时,只有系统关键窗口控件 (“最大化”、“ 最小化”、“ 关闭”和 “应用信息 ”图标) 保持可见。 这意味着用户几乎没有什么空间可供用户四处移动应用程序窗口。
可以使用 -webkit-app-region
CSS 属性为用户提供更多拖动应用的方法。 例如,如果应用有自己的标题栏,则可以将其标题栏转换为窗口拖动处理程序:
#title-bar {
position: fixed;
left: env(titlebar-area-x, 0);
top: env(titlebar-area-y, 0);
height: env(titlebar-area-height, 50px);
width: env(titlebar-area-width, 100%);
-webkit-app-region: drag;
}
覆盖更改React
用户可以在应用运行时切换标题栏或更改窗口尺寸。 了解这些事情何时发生对于你的应用非常重要。 你的应用可能需要重新排列标题栏中显示的某些内容,或重新排列页面上其他位置的布局。
若要侦听更改,请在 geometrychange
对象上使用 navigator.windowControlsOverlay
事件。 若要检测标题栏是否可见,请在 对象上使用 visible
navigator.windowControlsOverlay
属性。
请注意, geometrychange
当用户调整窗口大小时,会频繁触发 。 若要避免过于频繁地运行布局更改代码并导致应用中的性能问题,请使用 debounce
函数来限制事件的处理次数。 请参阅 限制和取消启动之间的差异。
const debounce = (func, wait) => {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
if ('windowControlsOverlay' in navigator) {
navigator.windowControlsOverlay.addEventListener('geometrychange', debounce(e => {
// Detect if the Window Controls Overlay is visible.
const isOverlayVisible = navigator.windowControlsOverlay.visible;
// Get the size and position of the title bar area.
const titleBarRect = e.titlebarAreaRect;
console.log(`The overlay is ${isOverlayVisible ? 'visible' : 'hidden'}, the title bar width is ${titleBarRect.width}px`);
}, 200));
}
演示应用
1DIV 是使用窗口控件覆盖功能的 PWA 演示应用。
在 Microsoft Edge 中,转到 1DIV 并安装应用。
单击应用 标题栏中 的“隐藏标题栏”。
应用现在一直将内容一直显示到窗口框架的顶部,其中标题栏曾经位于其中。 应用的顶部区域是拖动处理程序,可让用户移动窗口。
此演示应用的源代码位于 1DIV 存储库中。
manifest.json 源文件声明应用使用窗口控件覆盖功能。
app.js源文件使用
navigator.windowControlsOverlay
对象。app.css 源文件使用
titlebar-area-*
CSS 环境变量。