窗口管理

浏览器外部的 PWA 管理其自身的窗口。了解用于在操作系统中管理窗口的 API 和功能。

在由您的 PWA 管理的自有窗口中运行,具有该操作系统中任何窗口的所有优势和责任,例如

  • 在多窗口操作系统(如 Windows 或 ChromeOS)中移动和调整窗口大小的能力。
  • 与其他应用窗口共享屏幕,例如 iPadOS 分屏模式或 Android 分屏模式。
  • 出现在桌面上的 Dock、任务栏和 Alt+Tab 菜单中,以及移动设备上的多任务窗口列表中。
  • 随时最小化、跨屏幕和桌面移动窗口以及关闭窗口的能力。

移动和调整窗口大小

在桌面操作系统上,您的 PWA 窗口可以是任意大小,并且可以放置在屏幕上的任何位置。默认情况下,当用户在安装后首次打开 PWA 时,PWA 会获得当前屏幕百分比的默认窗口大小,最大分辨率为 1920x1080,位于屏幕的左上角。

用户可以移动和调整窗口大小,浏览器会记住上次的偏好设置。下次用户打开应用时,窗口将保留上次使用时的大小和位置。

无法在清单中定义 PWA 的首选大小和位置。您只能使用 JavaScript API 重新定位和调整窗口大小。您可以使用 moveTo(x, y)resizeTo(x, y) 函数,通过代码移动和调整您自己的 PWA 窗口,这些函数都属于 window 对象。

例如,您可以在 PWA 加载时使用以下代码调整和移动 PWA 窗口:

document.addEventListener("DOMContentLoaded", event => {
   // we can move only if we are not in a browser's tab
   isBrowser = matchMedia("(display-mode: browser)").matches;
   if (!isBrowser) {
      window.moveTo(16, 16);
      window.resizeTo(800, 600);
   }
});

您可以使用 window.screen 对象查询当前屏幕大小和位置;您可以使用 window 对象的 resize 事件检测窗口何时调整大小。没有用于捕获窗口移动的事件,因此您可以选择频繁查询位置。

除了绝对移动和调整窗口大小之外,您还可以使用 moveBy()resizeBy() 进行相对移动和调整大小。

浏览其他站点

如果您想将用户发送到 PWA 范围之外的外部站点,您可以使用标准的 <a href> HTML 元素。使用 location.href 或在兼容平台上打开新窗口。

当您访问 清单范围之外的网址时,PWA 的浏览器引擎会在您的窗口上下文中呈现应用内浏览器。

An in-app browser on a desktop PWA when browsing a URL that is out-of-scope.

应用内浏览器的一些功能包括:

  • 它们显示在您的内容之上。
  • 它们具有静态地址栏,显示当前来源、窗口标题和菜单。通常,它们的样式与清单的 theme_color 相符。
  • 您可以通过上下文菜单在浏览器中打开该网址。
  • 用户可以关闭浏览器或返回。

当应用内浏览器在屏幕上时,您的 PWA 会在后台等待,就像另一个窗口遮盖了它一样。

在独立 PWA 中浏览超出范围的网址时,iPhone 上的应用内浏览器。
在独立 PWA 中浏览超出范围的网址时,Android 上的应用内浏览器。

授权流程

许多 Web 身份验证和授权流程都需要将用户重定向到不同来源的不同网址,以获取返回到您的 PWA 来源的令牌,例如使用 OAuth 2.0

在这些情况下,应用内浏览器遵循以下流程:

  1. 用户打开您的 PWA 并点击登录。
  2. 您的 PWA 将用户重定向到 PWA 范围之外的网址,以便渲染引擎在您的 PWA 中打开应用内浏览器。
  3. 用户可以随时取消应用内浏览器并返回到您的 PWA。
  4. 用户登录应用内浏览器。身份验证服务器将用户重定向到您的 PWA 来源,并将令牌作为参数发送。
  5. 当应用内浏览器检测到属于 PWA 范围的网址时,它会自行关闭。
  6. 引擎将主 PWA 窗口导航重定向到身份验证服务器在应用内浏览器中访问的网址。
  7. 您的 PWA 获取令牌、存储令牌并呈现 PWA。

强制浏览器导航

如果您想强制使用浏览器打开网址,而不是应用内浏览器,您可以使用 <a href> 元素的 _blank 目标。这仅适用于桌面 PWA。在移动设备上,没有使用浏览器打开网址的选项。

function openBrowser(url) {
    window.open("url", "_blank", "");
}

打开新窗口

在桌面上,用户可以打开同一 PWA 的多个窗口。每个窗口对于相同的 start_url 都有不同的导航,就像您打开同一网址的两个浏览器标签页一样。在 PWA 的菜单中,用户可以选择文件,然后选择新建窗口。您可以通过 PWA 代码使用 open() 函数打开新窗口。

function openNewWindow() {
    window.open("/", "new-window", "width=600,height=600");
}

The same installed PWA with several windows opened on a desktop operating system.

当您在 iOS 或 iPadOS 上的 PWA 窗口中调用 open() 时,它会返回 null 并且不会打开窗口。在 Android 上打开新窗口会为网址创建一个新的应用内浏览器,即使该网址在您的 PWA 范围内,这通常也不会触发外部浏览体验。

窗口标题

<title> 元素主要用于 SEO 目的,因为浏览器标签页中的空间有限。当您从浏览器移动到 PWA 中的窗口时,所有标题栏空间都可供您使用。

您可以定义标题栏的内容:

  • 静态地在您的 HTML <title> 元素中定义。
  • 随时动态更改 document.title 字符串属性。

在桌面 PWA 上,标题至关重要,它用于窗口的标题栏,有时也用于任务管理器或多任务选择。如果您有单页应用,您可能希望在每个路由上更新您的标题。

标签页模式

标签页模式是一种实验性功能,可以让您的 PWA 具有基于标签页的设计,类似于 Web 浏览器。在这种情况下,用户可以在同一 PWA 中打开多个标签页,但所有标签页都绑定在同一操作系统窗口中。

您可以在 PWA 的标签页应用模式中阅读有关此实验性功能的更多信息。

窗口控件叠加层

我们已经提到,您可以通过定义 <title> 元素或 document.title 属性的值来更改窗口的标题。但它始终是一个字符串值。如果我们能够使用 HTML、CSS 和图片设计标题栏呢?窗口控件叠加层是 Microsoft Edge 和 Google Chrome 中桌面 PWA 的一项实验性功能,可能会有所帮助。

您可以在 自定义 PWA 标题栏的窗口控件叠加层中阅读有关此功能的更多信息。

With window controls overlay, you can render content in the title bar.

窗口管理

使用多个屏幕时,用户希望使用所有可用空间。例如:

  • 多窗口图形编辑器(如 Gimp)可以将各种编辑工具放置在精确定位的窗口中。
  • 虚拟交易平台可以在多个窗口中显示市场趋势,任何窗口都可以在全屏模式下查看。
  • 幻灯片应用可以在内部主屏幕上显示演讲者备注,并在外部投影仪上显示演示文稿。

窗口管理 API 允许 PWA 执行此操作以及更多操作。

获取屏幕详细信息

窗口管理 API 添加了一个新方法 window.getScreenDetails(),该方法返回一个对象,其中包含屏幕作为附加屏幕的不可变数组。还有一个可以从 ScreenDetails.currentScreen 访问的实时对象,它对应于当前的 window.screen

screens 数组更改时,返回的对象还会触发 screenschange 事件。(当单个屏幕上的属性更改时,不会发生这种情况。)当单个屏幕(window.screenscreens 数组中的屏幕)的属性更改时,也会触发 change 事件。

// Request an object with a screen objects
const screenDetails = await window.getScreenDetails();
screenDetails.screens[0].isPrimary;  // e.g. true
screenDetails.screens[0].isInternal;  // e.g. true
screenDetails.screens[0].label;  // e.g. 'Samsung Electric Company 28"'

// Access the live object corresponding to the current `window.screen`.
// The object is updated on cross-screen window placements or device changes.
screenDetails.currentScreen;
screenDetails.addEventListener('screenschange', function() {
 // NOTE: Does not fire on changes to attributes of individual screens.
  const screenCount = screenDetails.screens.length;
  const currentScreen screenDetails.currentScreen.id;
});

如果用户或操作系统将 PWA 的窗口从一个屏幕移动到另一个屏幕,则还会从屏幕详细信息对象触发 currentscreenchange 事件

屏幕唤醒锁定

想象一下。您在厨房里用平板电脑查看食谱。您刚刚完成食材的准备工作。您的双手很脏,您转过身回到您的设备以阅读下一步。糟糕!屏幕变黑了!屏幕唤醒锁定 API 为您提供帮助,并允许 PWA 阻止屏幕变暗、休眠或锁定,从而让用户可以停止、开始、离开和返回,而无需担心。

// Request a screen wake lock
const wakeLock = await navigator.wakeLock.request();

// Listen for wake lock release
wakeLock.addEventListener('release', () => {
 console.log(`Screen Wake Lock released: ${wakeLock.released}`);
});
// Manually release the wake lock
wakeLock.release();

虚拟键盘

基于触摸的设备(如手机和平板电脑)提供虚拟屏幕键盘,以便用户在 PWA 的表单元素获得焦点时进行输入。

借助 VirtualKeyboard API,您的 PWA 可以使用 navigator.virtualKeyboard 接口更好地控制兼容平台上的键盘。

  • 使用 navigator.virtualKeyboard.show()navigator.virtualKeyboard.hide() 显示和隐藏虚拟键盘。
  • 通过将 navigator.virtualKeyboard.overlaysContent 设置为 true,告知浏览器您要自行关闭虚拟键盘。
  • 使用 geometrychange 事件了解键盘何时出现和消失。
  • 通过将 contenteditable 设置为 automanual,以及使用 virtualkeyboardpolicy HTML 属性,在编辑宿主元素上设置虚拟键盘策略。策略允许您决定是否希望虚拟键盘由浏览器自动处理 (auto) 或由您的脚本处理 (manual)。
  • 使用 CSS 环境变量获取有关虚拟键盘外观的信息,例如 keyboard-inset-heightkeyboard-inset-top

使用 VirtualKeyboard API 进行完全控制中阅读有关此 API 的更多信息。