能力中的 API
屏幕方向 API(锁定与解锁)
发布于 更新于
屏幕方向 API 通过 screen.orientation 暴露文档的方向。它报告当前类型和角度、触发 change 事件,并提供请求方向锁定的 lock() 与解除锁定的 unlock()(Screen Orientation,W3C)。
支持范围
链接到“支持范围”一节MDN 将 ScreenOrientation 接口标为广泛可用,但将 lock() 标为有限可用。MDN 还指出,方向锁定通常在移动设备的浏览器上下文进入全屏时启用;规范则允许用户代理把全屏或已安装的 Web 应用设为锁定前提(ScreenOrientation: lock() method,MDN;Screen Orientation,W3C)。
screen.orientation.typescreen.orientation.anglescreen.orientation.addEventListener("change", listener)
await screen.orientation.lock(orientation)screen.orientation.unlock()应用锁定后,lock() 返回的 Promise 以 undefined 兑现。unlock() 返回 undefined;规范解释,用户代理可能无法预知回到默认方向是否会改变屏幕(Screen Orientation,W3C)。
screen.orientation 是 ScreenOrientation 对象,包含规范定义的以下成员。
| 成员 | 类型 | 说明 |
|---|---|---|
type |
OrientationType(只读) |
当前值:portrait-primary、portrait-secondary、landscape-primary 或 landscape-secondary。 |
angle |
unsigned short(只读) |
屏幕相对其自然方向逆时针旋转的角度。 |
lock(orientation) |
Promise<undefined> |
请求锁定到一个 OrientationLockType 值。 |
unlock() |
undefined |
解除活动锁定并回到默认方向。 |
onchange |
EventHandler |
处理报告的方向类型或角度改变时触发的 change 事件。 |
orientation 参数接受 any、natural、landscape、portrait、portrait-primary、portrait-secondary、landscape-primary 或 landscape-secondary。规范允许用户代理或平台只支持其中一部分锁定值(OrientationLockType enum,W3C)。
规范为 lock() 定义了以下失败情况。
它的通用安全检查也会同步应用于 unlock()。
| 异常 | 条件 |
|---|---|
InvalidStateError |
文档不是受到用户关注的顶级可遍历对象的 fully active 后代。 |
SecurityError |
文档已隐藏,或设置了 sandboxed orientation lock 标志。 |
NotSupportedError |
用户代理无法锁定到请求的值,或平台、用户偏好或其他限制阻止了尝试。 |
NotAllowedError |
用户代理要求锁定前提,例如全屏或已安装的 Web 应用,而文档不满足条件。 |
AbortError |
另一个 lock() 请求会取消待处理的锁定请求。屏幕存在活动方向锁定时,unlock() 也会取消该请求。 |
unlock() 会先检查屏幕的活动方向锁定。该值为 null 时,方法会在检查待处理的锁定 Promise 前返回 undefined。否则,待处理的锁定 Promise 会以 AbortError 拒绝,随后用户代理应用默认方向锁定(Screen Orientation,W3C)。
下面的示例会先检测要使用的屏幕方向成员。各自的回退分支保留响应式行为,不尝试不可用的操作。
检测支持后锁定查看器
链接到“检测支持后锁定查看器”一节把这段脚本粘贴到页面中。它会创建按钮和状态输出,锁定前请求全屏,并在下一次点击时解除两种状态。
const button = document.createElement("button");const status = document.createElement("output");button.textContent = "锁定横向";document.body.append(button, status);
let locked = false;
button.addEventListener("click", async () => { const orientation = screen.orientation;
if (typeof orientation?.lock !== 'function') { const axis = matchMedia("(orientation: portrait)").matches ? "纵向" : "横向"; status.value = `锁定不可用;响应式布局当前为${axis}。`; return; }
try { if (!locked) { if (!document.fullscreenElement) { await document.documentElement.requestFullscreen(); } await orientation.lock("landscape"); locked = true; button.textContent = "解除方向锁定"; status.value = `已锁定:${orientation.type},${orientation.angle} 度。`; } else { orientation.unlock(); if (document.fullscreenElement) await document.exitFullscreen(); locked = false; button.textContent = "锁定横向"; status.value = "方向已解锁。"; } } catch (error) { status.value = `${error.name}:未锁定方向。`; }});catch 分支处理被拒绝的全屏和方向请求。功能检测分支把布局控制权留给 CSS,因此 lock() 缺失时页面仍可使用。
跟随方向变化
链接到“跟随方向变化”一节在 change 处理函数中重新读取 type 与 angle,因为该事件表示这些报告值已经改变。
function renderOrientation() { const current = screen.orientation; document.documentElement.dataset.orientation = current.type; console.log(`${current.type}:${current.angle} 度`);}
if (screen.orientation) { screen.orientation.addEventListener("change", renderOrientation); renderOrientation();} else { const portrait = matchMedia("(orientation: portrait)"); const renderFallback = () => { document.documentElement.dataset.orientation = portrait.matches ? "portrait" : "landscape"; }; portrait.addEventListener("change", renderFallback); renderFallback();}回退保留纵向或横向的区别,但不会虚构媒体查询没有提供的 primary 或 secondary 方向值。
另请参阅
链接到“另请参阅”一节- orientation 清单成员
- display 清单成员
- Window Management API
- Screen Orientation(w3.org)
- ScreenOrientation interface(developer.mozilla.org)
- ScreenOrientation: lock() method(developer.mozilla.org)
规范
| 规范 | 状态 |
|---|---|
| Screen Orientation: ScreenOrientation interface | W3C 草案 |
| Screen Orientation: lock() method | W3C 草案 |
| Screen Orientation: unlock() method | W3C 草案 |