H5 移动端保持屏幕常亮:Wake Lock API 实战指南
在移动端 H5 应用中,很多场景都需要让屏幕保持常亮,例如视频播放、运动计步、电子书阅读、远程监控等。如果设备进入睡眠状态,不仅影响用户体验,还可能导致关键操作中断。过去,我们依赖 NoSleep.js 这类库来实现屏幕常亮,但现代浏览器已经提供了官方 Wake Lock API,让我们可以更高效、安全地控制屏幕唤醒状态。
本文将详细介绍 Wake Lock API 的使用方法、兼容性问题以及实战示例。
1. 检测浏览器是否支持 Wake Lock
在使用 Wake Lock API 前,首先需要判断当前浏览器是否支持该功能:
const canWakeLock = () => 'wakeLock' in navigator;
if (canWakeLock()) {
console.log('当前浏览器支持 Wake Lock API');
} else {
console.warn('当前浏览器不支持 Wake Lock API,需要使用 polyfill 或 NoSleep.js');
}
⚠️ 注意:截至目前,Chrome 85+ 支持该 API,而 Safari 尚未支持。在 iOS 端,我们仍需使用 polyfill 或 NoSleep.js。
2. 请求屏幕唤醒锁
Wake Lock API 提供了 navigator.wakeLock.request()
方法来请求屏幕常亮状态,它返回一个 WakeLockSentinel 对象:
let wakeLock = null;
const requestWakeLock = async () => {
try {
wakeLock = await navigator.wakeLock.request('screen');
console.log('Wake Lock 已激活,屏幕将保持常亮!');
} catch (err) {
console.error(`无法获取 Wake Lock: ${err.name} - ${err.message}`);
}
};
// 调用函数请求唤醒锁
requestWakeLock();
说明:该方法基于 Promise,可以在异步函数中调用,并捕获异常。
3. 释放唤醒锁
如果不再需要保持屏幕常亮,可以手动释放唤醒锁:
if (wakeLock) {
wakeLock.release().then(() => {
wakeLock = null;
console.log('Wake Lock 已释放');
});
}
释放后,设备将恢复正常的屏幕睡眠策略。
4. 侦听唤醒锁释放事件
当唤醒锁因任何原因(如用户切换标签页、浏览器最小化)被释放时,会触发 release
事件,我们可以监听它来进行处理:
if (wakeLock) {
wakeLock.addEventListener('release', () => {
console.log('Wake Lock 被释放');
});
}
5. 自动重新获取唤醒锁
由于唤醒锁只在活动标签页生效,当页面可见性改变时,我们可以重新请求唤醒锁,保证用户体验连续:
document.addEventListener('visibilitychange', async () => {
if (wakeLock !== null && document.visibilityState === 'visible') {
await requestWakeLock();
console.log('页面重新可见,Wake Lock 已重新获取');
}
});
这样即便用户切换应用或锁屏,再返回页面时,屏幕仍能保持唤醒状态。
6. 完整示例
let wakeLock = null;
const canWakeLock = () => 'wakeLock' in navigator;
const requestWakeLock = async () => {
if (!canWakeLock()) return console.warn('浏览器不支持 Wake Lock API');
try {
wakeLock = await navigator.wakeLock.request('screen');
console.log('Wake Lock 已激活!');
wakeLock.addEventListener('release', () => {
console.log('Wake Lock 被释放');
});
} catch (err) {
console.error(`获取 Wake Lock 失败: ${err.name} - ${err.message}`);
}
};
// 页面加载或用户操作时请求唤醒锁
document.getElementById('startButton').addEventListener('click', requestWakeLock);
// 页面可见性改变时重新请求唤醒锁
document.addEventListener('visibilitychange', async () => {
if (wakeLock !== null && document.visibilityState === 'visible') {
await requestWakeLock();
}
});
HTML 配套:
<button id="startButton">保持屏幕常亮</button>
7. 总结
- Wake Lock API 是官方提供的屏幕常亮方案,比 NoSleep.js 更加高效、轻量。
- 仅适用于活动标签页/窗口,后台标签页无法保持唤醒状态。
- 可以通过
release
事件和visibilitychange
自动处理锁释放和重新获取。 - iOS Safari 尚未支持,需要 polyfill 或备用方案。
通过合理使用 Wake Lock API,H5 应用可以在视频播放、计步器、游戏等场景下提供更加流畅和持续的用户体验。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>移动端保持屏幕常亮 Demo</title>
<style>
body {
font-family: "Microsoft YaHei", sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
background: #f0f4f8;
}
button {
padding: 12px 24px;
font-size: 16px;
border: none;
border-radius: 6px;
background-color: #007aff;
color: #fff;
cursor: pointer;
margin-bottom: 20px;
}
button:disabled {
background-color: #999;
cursor: not-allowed;
}
#status {
font-size: 18px;
color: #333;
}
</style>
</head>
<body>
<h2>移动端保持屏幕常亮 Demo</h2>
<button id="wakeButton">开启屏幕常亮</button>
<div id="status">状态:未激活</div>
<!-- iOS polyfill 引入 NoSleep.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/nosleep/0.12.0/NoSleep.min.js"></script>
<script>
const statusEl = document.getElementById('status');
const wakeButton = document.getElementById('wakeButton');
let wakeLock = null;
const noSleep = new NoSleep();
// 检测是否支持 Wake Lock API
const canWakeLock = () => 'wakeLock' in navigator;
// 请求唤醒锁
const requestWakeLock = async () => {
if (canWakeLock()) {
try {
wakeLock = await navigator.wakeLock.request('screen');
statusEl.textContent = '状态:Wake Lock 已激活';
console.log('Wake Lock 已激活!');
wakeLock.addEventListener('release', () => {
statusEl.textContent = '状态:Wake Lock 被释放';
console.log('Wake Lock 被释放');
});
} catch (err) {
statusEl.textContent = `状态:获取 Wake Lock 失败 (${err.name})`;
console.error(err);
}
} else {
// iOS 不支持 Wake Lock API,使用 NoSleep.js
noSleep.enable();
statusEl.textContent = '状态:NoSleep 已激活 (iOS Polyfill)';
console.log('NoSleep 已激活');
}
};
// 页面可见性改变时,重新请求唤醒锁
document.addEventListener('visibilitychange', async () => {
if (document.visibilityState === 'visible') {
if (wakeLock) await requestWakeLock();
}
});
wakeButton.addEventListener('click', requestWakeLock);
</script>
</body>
</html>