使用窗口控件覆盖在标题栏区域中显示内容

安装在桌面上的渐进式 Web 应用 (PWA) 可以使用窗口控件覆盖 API 显示标题栏通常所在的内容,使 PWA 感觉更原生。

窗口控件覆盖 API 执行以下操作:

  • 允许在应用的整个外围应用上显示 Web 内容。
  • 将系统所需的关键窗口控件移动到覆盖层中。
  • 使内容能够远离此覆盖。

渐进式 Web 应用 (PWA) 可以使用 Web 应用清单文件中的显示成员来定义在移动平台上的 显示 方式。 但是,若要创建类似于本机的沉浸式体验, 桌面 PWA 可以使用另一种方法。

默认情况下,安装在桌面上的 PWA 可以在紧邻保留标题栏区域下方的区域中显示内容:

Windows 上的 PWA 应用,显示应用内容显示在保留标题栏区域下方

显示标题栏通常所在的内容可以帮助 PWA 感觉更原生。 许多桌面应用程序(例如 Visual Studio Code、Microsoft Teams 和 Microsoft Edge)都已执行此操作:

Visual Studio Code 在标题栏区域中显示内容

在应用中启用窗口控件覆盖

首先,在应用的 Web 应用清单文件中启用窗口控件覆盖功能。 为此,请在清单文件中设置 display_override 属性:

{
  "display_override": ["window-controls-overlay"]
}

另请参阅:

切换标题栏

启用“窗口控件覆盖”功能后,用户可以通过单击标题栏切换按钮来选择是否拥有标题栏:

选择标题栏切换按钮

代码不能假定窗口控件覆盖已显示,因为:

  • 用户可以选择是否显示标题栏。
  • 你的应用还可以在 Web 浏览器或移动设备中运行,以及作为桌面应用运行。

因此,代码需要对标题栏几何图形更改做出反应。 若要了解详细信息,请参阅 响应覆盖更改

使用 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;
}

响应覆盖更改

用户可以在应用运行时切换标题栏或更改窗口尺寸。 了解这些事情何时发生对于你的应用非常重要。 你的应用可能需要重新排列标题栏中显示的某些内容,或重新排列页面上其他位置的布局。

若要侦听更改,请在 geometrychange 对象上使用 navigator.windowControlsOverlay 事件。 若要检测标题栏是否可见,请在 对象上使用 visiblenavigator.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 演示应用。

  1. 在 Microsoft Edge 中,在新窗口或选项卡中打开 1DIV 演示应用。

  2. 在“地址”栏中,单击“ 可用应用”。安装 1DIV (“应用应用可用。“安装 1DIV”图标) 按钮。 此时会打开 “安装 1DIV 应用 ”对话框。

  3. 单击“ 安装 ”按钮。 1DIV 应用在自己的窗口中打开,并打开 “已安装应用 ”对话框:

    1DIV 应用在其自己的窗口中显示“已安装应用”对话框

  4. 单击对话框的 “关闭 (X) ”按钮。 (或选中或清除复选框,然后单击“ 允许 ”按钮。)

    应用的标题栏至少包含以下窗口控件:

    图标 工具提示
    “隐藏标题栏”图标 隐藏标题栏
    “设置和更多”图标 设置等
    “最小化”图标 Minimize
    “还原”图标 还原
    “关闭”图标 Close
  5. 在标题栏中,单击“ 隐藏标题栏 ” (“隐藏标题栏”图标) 按钮。

    应用现在一直显示到窗口框架顶部的内容,其中标题栏曾经是:

    地图的顶部区域可用于移动窗口

    应用的顶部区域是一个拖动手柄,允许用户移动窗口。

此演示应用的源代码位于 1DIV 存储库中。

  • manifest.json源文件声明应用使用窗口控件覆盖功能。

  • app.js 源文件使用 navigator.windowControlsOverlay 对象。

  • app.css源文件使用 titlebar-area-* CSS 环境变量。

在不安装 PWA 的情况下预览自定义覆盖层

在 Microsoft Edge DevTools 的应用程序工具中 ,可以模拟窗口控件覆盖 (WCO) 功能,而无需先安装 PWA 并启用 WCO 功能。 通过从 DevTools 中模拟 WCO 功能,可以比重新安装修订后的 PWA 更快地测试标题栏区域的 CSS 代码更改。

模拟覆盖是静态图像。 CSS 变量 env(titlebar-area-left)env(titlebar-area-top)env(titlebar-area-width)env(titlebar-area-height) 的值设置为与所选平台匹配。

请参阅 在不安装 PWA 的情况下模拟窗口控件覆盖 API

另请参阅