ios 13+ safari 访问陀螺仪需在用户手势中调用 deviceorientationevent.requestpermission() 获取权限,返回 "granted"/"denied"/"prompt",须检查字符串值而非仅依赖 promise 状态,并兼容不支持该方法的浏览器。

iOS 13+ 必须显式调用 DeviceOrientationEvent.requestPermission()
iOS 13 起,Safari 默认禁止网页访问陀螺仪(deviceorientation)和加速度计(devicemotion)数据,除非用户主动授权。不调用 requestPermission() 就直接监听事件,deviceorientation 事件根本不会触发——连第一次也不发,不是“没数据”,是彻底被拦截。
这个权限不是「一次授权永久有效」:它只在当前页面生命周期内有效;刷新页面、导航离开再返回,都得重新申请。
实操建议:
- 必须在用户手势(如
click、touchend)回调中调用DeviceOrientationEvent.requestPermission(),否则 iOS 会静默拒绝(返回"denied") - 不能在
DOMContentLoaded或load里提前调,那不算用户意图明确的手势上下文 - 调用后需显式处理 Promise:成功才开始监听
deviceorientation,失败要给用户可操作的重试入口(比如按钮)
requestPermission() 的返回值和错误处理
该方法返回一个 Promise,但它的行为和常见 API 不同:即使用户点了「不允许」,Promise 也**可能 resolve**(返回 "denied"),而不是 reject。iOS 实际返回值只有三种:"granted"、"denied"、"prompt"(极少出现,通常只在首次未决时)。
常见错误现象:只写 .then() 忽略 .catch(),结果用户拒绝后无反馈,页面卡死在“等待权限”状态。
实操建议:
- 始终用
.then(permissionState => { ... })检查permissionState字符串值,别依赖是否进then判断成功 - 如果得到
"denied",提示用户「需手动开启:设置 → Safari → 传感器访问 → 允许」,因为 iOS 不提供 JS 触发系统设置页的接口 - 避免连续多次调用:iOS 对频繁弹窗有频率限制,短时间内重复调用会直接返回
"denied"
监听 deviceorientation 前必须确认权限状态
即使刚调过 requestPermission() 并拿到 "granted",也不能假设后续每次都能收到事件。iOS 可能在后台标签页、低电量模式、或页面失焦时暂停传感器推送,且不会通知 JS。
使用场景:AR 类应用、体感交互游戏、倾斜控制滚动等,都依赖持续稳定的事件流。
实操建议:
- 监听前先检查
DeviceOrientationEvent.permission(仅 Safari 支持),但注意它可能滞后于实际状态,仍要以requestPermission()的 Promise 结果为准 - 加一层心跳检测:记录上一次
deviceorientation事件时间戳,超过 500ms 无新事件,就认为中断,提示用户「请唤醒屏幕并保持前台」 - 不要用
setTimeout模拟 fallback,陀螺仪数据不可预测,插值毫无意义
兼容旧版 iOS 和非 Safari 浏览器的写法
Android Chrome、Firefox、桌面 Safari 等多数浏览器不支持 requestPermission(),直接调用会报 TypeError: DeviceOrientationEvent.requestPermission is not a function。
性能影响:在不支持的环境里做 feature detect 是零开销的,但若漏掉判断,整个脚本可能因报错中断。
实操建议:
- 用
typeof DeviceOrientationEvent.requestPermission === 'function'做安全判断,只在 iOS Safari 中走权限流程 - 对不支持的浏览器,直接
addEventListener('deviceorientation', handler)即可(它们默认允许) - 别试图用
try/catch包裹requestPermission()来统一逻辑——失败原因太多(网络、手势缺失、系统策略),catch 住也没法自动恢复
最易被忽略的一点:iOS 上 deviceorientation 的 alpha 值在页面未获得焦点时恒为 null,哪怕权限已授。必须确保页面处于 active 状态,且用户视线在视口内——这不是 bug,是 Safari 的主动节能策略。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











