如何在 JavaScript 中使用全屏 API(并用 Wake Lock API 保持屏幕常亮)

如何在 JavaScript 中使用全屏 API(并用 Wake Lock API 保持屏幕常亮)

💡 原文英文,约3300词,阅读约需12分钟。
📝

内容提要

本文介绍浏览器全屏 API 的实用技巧:使用 requestFullscreen() 和 exitFullscreen() 切换全屏,且必须由用户手势触发;通过 fullscreenchange 事件同步 UI,用 :fullscreen 伪类设置样式;兼容旧版 Safari 的 webkit 前缀,iPhone 不支持元素全屏,需降级为固定定位覆盖层;再用 Wake Lock API 防止屏幕休眠,并给出约六十行的可复用完整代码模式。

🔎

延伸解读

用户手势限制:为何不能自动全屏

文章强调 requestFullscreen() 必须在用户手势(如点击、按键)的短暂激活窗口内调用,否则 Promise 会拒绝。这意味着不能在页面加载、定时器或网络请求后自动全屏。若需先执行异步操作,应先调用全屏再处理耗时任务,否则激活窗口可能已过期。这一设计是为了防止恶意页面劫持屏幕。

iPhone 全屏限制与降级方案

文章指出 iPhone Safari 不支持任意元素的全屏 API,仅 <video> 可用,且 document.fullscreenEnabled 为 false。Chrome 和 Firefox 在 iOS 上同样受限。可行的降级方案是使用 position: fixed; inset: 0 的伪全屏覆盖层,或建议用户“添加到主屏幕”以 standalone 模式运行。文章建议不要仅依赖特性检测,而应将运行时拒绝作为触发降级的信号。

Wake Lock 的自动释放与重新获取

文章说明 Wake Lock 在页面隐藏时会被浏览器自动释放,且不会自动恢复。因此需要在 visibilitychange 事件中检查页面是否可见,并重新请求锁。同时,Wake Lock 需要安全上下文(HTTPS),在省电模式下可能被拒绝。文章建议将 Wake Lock 与 fullscreenchange 事件绑定,进入全屏时请求,退出时释放,以节省电量。

全屏状态同步与键盘可访问性

文章强调不要用自定义变量跟踪全屏状态,而应始终读取 document.fullscreenElement 并监听 fullscreenchange 事件,因为用户可能通过 Esc 或浏览器按钮退出。同时,全屏表面应设置 tabindex="0" 并支持 Enter/Space 键,确保键盘用户可操作。快捷键需避免与页面自身按键冲突,例如在打字页面中 F 键仅用于进入全屏,退出交给 Esc。

❓

Q&A

为什么调用 requestFullscreen() 会报错说只能由用户手势触发?

因为浏览器要求 requestFullscreen() 必须在用户与页面交互后的短暂激活窗口内调用,比如点击、按键或触摸。如果在页面加载时、定时器里,或者在 await 一个耗时操作(如 fetch)之后才调用,激活窗口可能已经过期,Promise 就会拒绝并提示需要用户手势。这是为了防止页面自动劫持全屏。

如何让全屏状态下的按钮文字和样式自动更新?

不要自己用变量记录全屏状态,而应该监听 document 上的 fullscreenchange 事件,在事件处理函数里读取 document.fullscreenElement 来判断当前是否全屏,然后更新按钮文字、aria-pressed 属性以及 body 的类名。这样无论用户通过 Esc、浏览器按钮还是其他方式退出全屏,UI 都能保持同步。

iPhone 上为什么不能对 div 使用全屏 API?有什么替代方案?

iPhone 上的 Safari 不支持对任意元素使用 Fullscreen API,只支持 video 元素。替代方案有两种:一是使用“伪全屏”回退,即用 position: fixed; inset: 0 覆盖整个视口并隐藏自己的界面元素;二是建议用户将网页添加到主屏幕,并通过 manifest 中的 display: standalone 让应用以无浏览器界面的方式运行。

Wake Lock API 怎么用?为什么页面隐藏后屏幕又会自动锁屏?

使用 navigator.wakeLock.request('screen') 请求屏幕唤醒锁,返回一个 Promise。当页面隐藏(如切换标签、最小化窗口)时,浏览器会自动释放锁,并且不会自动重新获取。因此需要在 visibilitychange 事件中检查页面是否可见,如果可见且仍需要保持唤醒,就重新请求锁。另外,唤醒锁需要 HTTPS 环境,且可能因省电模式被拒绝。

如何兼容旧版 Safari 的全屏 API?

旧版 Safari(16.4 之前)需要使用 webkit 前缀的方法和属性,如 webkitRequestFullscreen()、webkitExitFullscreen()、webkitFullscreenElement 以及 webkitfullscreenchange 事件。可以写一个小的兼容层,封装 request 和 exit 方法,并同时监听 fullscreenchange 和 webkitfullscreenchange 事件,这样代码在其他浏览器中也能正常工作。

全屏时如何防止屏幕变暗或休眠?

可以使用 Screen Wake Lock API,在进入全屏时请求唤醒锁,退出全屏时释放。具体做法是监听 fullscreenchange 事件,当进入全屏时调用 navigator.wakeLock.request('screen'),退出时调用 wakeLock.release()。同时注意在页面重新可见时重新请求锁,并只在需要保持屏幕常亮时持有锁,以节省电量。

🏷️

标签

➡️

继续阅读