能力 · API
Generic Sensor API
发布于 更新于
Generic Sensor API 是一个 Sensor 基接口(start()、stop(),以及 reading、activate、error 事件),由具体的设备传感器继承:Accelerometer、LinearAccelerationSensor、GravitySensor、Gyroscope、AbsoluteOrientationSensor、RelativeOrientationSensor、Magnetometer 和 AmbientLightSensor。页面构造某个具体类,调用 start(),然后在 reading 处理函数中从属性读取最新采样;读数只会投递给安全上下文中可见且获得焦点的文档。
支持情况是仅 Chromium 一家,内部还分两档。Chrome 67(Edge 79、Samsung Internet 9.0、Android WebView 67)无需标志即提供 Accelerometer、LinearAccelerationSensor、Gyroscope、AbsoluteOrientationSensor 与 RelativeOrientationSensor,Chrome 91 加入 GravitySensor。Magnetometer 与 AmbientLightSensor 自 Chrome 56 起存在,但只在 chrome://flags/#enable-experimental-web-platform-features 之后。Firefox 与 Safari 没有实现其中任何一个接口(BCD api.Accelerometer、api.Magnetometer、api.AmbientLightSensor);跨内核获取运动数据的回退路径是 DeviceMotionEvent。
new Accelerometer()new Accelerometer(options)new Gyroscope(options)new AbsoluteOrientationSensor(options)new Magnetometer(options)new AmbientLightSensor(options)
sensor.start()sensor.stop()构造函数是同步的,返回一个处于 idle 状态的传感器。start() 与 stop() 返回 undefined;激活异步完成,以 activate 事件通知,之后 activated 为 true,第一份采样到达时 hasReading 变为 true,timestamp 携带该采样的 DOMHighResTimeStamp。运动类传感器暴露 x、y、z(加速度计为 m/s²,Gyroscope 为 rad/s,Magnetometer 为 µT);方向类传感器暴露 quaternion 与 populateMatrix(target);AmbientLightSensor 暴露以 lux 计的 illuminance。所有接口都带 [SecureContext]。
每个构造函数接受一个可选的 options 字典。基类 SensorOptions 只有一个成员;运动与方向类传感器在其上扩展了 referenceFrame。
| 成员 | 类型 | 必填 | 适用于 | 说明 |
|---|---|---|---|---|
frequency |
double(Hz) |
否 | 所有传感器 | 期望的采样与上报频率。规范把它定为提示:浏览器可以把它钳制到平台传感器的范围内。Chromium 把加速度计、陀螺仪和方向传感器的上限定为 60 Hz(默认 10 Hz),Magnetometer 与 AmbientLightSensor 上限为 10 Hz(sensor_traits.h)。 |
referenceFrame |
"device" 或 "screen" |
否,默认 "device" |
Accelerometer、LinearAccelerationSensor、GravitySensor、Gyroscope、Magnetometer、两种方向传感器 |
读数所用的坐标系。"screen" 让坐标轴随当前屏幕方向旋转,横放的平板仍把“上”报告为 y 轴正方向。 |
读数在抵达页面前已被量化:Accelerometer 规范把 x、y、z 四舍五入到最接近的 0.1 m/s²,这是一项反指纹措施,也决定了你能检测到的最小运动幅度。
构造函数同步抛出;start() 从不抛出,而是通过 error 事件报告失败,event.error 即下表中的 DOMException。
| 异常 | 位置 | 条件 |
|---|---|---|
SecurityError |
构造函数 | 文档不被允许使用该传感器的 policy-controlled feature(accelerometer、gyroscope、magnetometer 或 ambient-light-sensor;方向传感器需要 accelerometer 加 gyroscope,绝对方向传感器还需要 magnetometer)。跨源 iframe 需要在 allow 属性中列出它们。 |
NotSupportedError |
构造函数 | options 含有该传感器类型不支持的键(「initialize a sensor object」步骤)。 |
NotAllowedError |
error 事件 |
传感器权限请求的结果为 "denied"。Chromium 把这些权限对应到 navigator.permissions.query() 中的 accelerometer、gyroscope、magnetometer、ambient-light-sensor 名称。 |
NotReadableError |
error 事件 |
「connect to sensor」失败:设备没有这种传感器、平台拒绝提供,或传感器在使用中停止。传感器回到 "idle" 并保持沉默,直到再次调用 start()。 |
new Magnetometer() 抛出的 ReferenceError 不是传感器错误,它表示当前浏览器没有定义这个构造函数,这是该做特性检测而不是 catch 的情形。
示例精确检测所需的构造函数,缺失时回退到 Firefox 与 Safari 都实现的 DeviceMotionEvent,两条路径都没有时退回静态 UI。
用 Accelerometer 检测摇一摇,并以 DeviceMotionEvent 回退
Section titled “用 Accelerometer 检测摇一摇,并以 DeviceMotionEvent 回退”优先走加速度计路径,因为它按你选择的频率投递经过校准和量化的采样。构造函数缺失时,同一套阈值跑在 devicemotion 上,它报告的是未量化的 accelerationIncludingGravity。
const SHAKE_THRESHOLD = 25; // m/s^2,合成幅值
function onShake(callback) { if ('Accelerometer' in window) { let sensor; try { sensor = new Accelerometer({ frequency: 30 }); } catch (err) { console.warn(`${err.name}: ${err.message}`); // 被 Permissions Policy 拦下 return false; } sensor.addEventListener('error', (event) => { console.warn(`${event.error.name}: ${event.error.message}`); }); sensor.addEventListener('reading', () => { if (Math.hypot(sensor.x, sensor.y, sensor.z) > SHAKE_THRESHOLD) callback(); }); sensor.start(); return true; }
if ('DeviceMotionEvent' in window) { window.addEventListener('devicemotion', (event) => { const a = event.accelerationIncludingGravity; if (a && Math.hypot(a.x, a.y, a.z) > SHAKE_THRESHOLD) callback(); }); return true; }
return false; // 没有运动数据:改为显示一个按钮}
if (!onShake(() => document.body.classList.toggle('shaken'))) { document.querySelector('#shake-button').hidden = false;}iOS 13 及之后的 devicemotion 本身也受 DeviceMotionEvent.requestPermission() 门控,且必须在用户手势中调用;真实应用里这段回退分支应放在一次点击之后。
构造方向传感器前先查询权限
Section titled “构造方向传感器前先查询权限”AbsoluteOrientationSensor 同时依赖三项权限。先查询它们,页面就能说明哪一项被拦,而不是等 error 事件里的 NotAllowedError。
async function startCompass(onHeading) { if (!('AbsoluteOrientationSensor' in window)) return 'unsupported';
const names = ['accelerometer', 'gyroscope', 'magnetometer']; const states = await Promise.all( names.map((name) => navigator.permissions.query({ name }).then((s) => s.state)), ); if (states.includes('denied')) return 'denied';
const sensor = new AbsoluteOrientationSensor({ frequency: 10, referenceFrame: 'screen' }); sensor.addEventListener('reading', () => { const [qx, qy, qz, qw] = sensor.quaternion; const yaw = Math.atan2(2 * (qw * qz + qx * qy), 1 - 2 * (qy * qy + qz * qz)); onHeading(((yaw * 180) / Math.PI + 360) % 360); }); sensor.addEventListener('error', (event) => { if (event.error.name === 'NotReadableError') onHeading(null); // 此设备没有磁力计 }); sensor.start(); return 'started';}返回字符串让调用方渲染三种状态:指南针、“请开启运动访问权限”的提示,或 API 不存在时正北朝上的普通地图。
- Geolocation API,另一项与位置相关、带
PERMISSION_DENIED分支的权限 - Idle Detection API,另一项由 Permissions API 门控的仅 Chromium 能力
- Screen Wake Lock API,常与运动追踪界面搭配
- Generic Sensor API: Sensor.start()(w3.org)
- Generic Sensor API: Mitigation strategies(w3.org)
- Accelerometer: reading quantization algorithm(w3.org)
- Sensors for the web(developer.chrome.com)
规范
- 图例
- 支持
- 部分支持
- 需开启标志
- 不支持
- 未知
| 浏览器 / 平台 | 支持 | 版本 | 置信度 | 来源 | 备注 |
|---|---|---|---|---|---|
| Chrome (Desktop) | 支持 | 67 | 高 | 来源 | — |
| Chrome (Android) | 支持 | 67 | 高 | 来源 | 1 |
| Edge (Desktop) | 支持 | 79 | 高 | 来源 | 2 |
| Firefox (Desktop) | 不支持 | — | 高 | 来源 | 3 |
| Firefox (Android) | 不支持 | — | 高 | 来源 | 45 |
| Safari (macOS) | 不支持 | — | 高 | 来源 | 6 |
| Safari (iOS) | 不支持 | — | 高 | 来源 | 78 |
| Samsung Internet | 支持 | 9.0 | 高 | 来源 | 9 |
| WebView (Android) | 支持 | 67 | 高 | 来源 | 10 |
- 由 browser-compat-data 镜像自 Chrome 的数据推导。
- 由 browser-compat-data 镜像自 Chrome 的数据推导。
- browser-compat-data 未记录 Firefox 的支持。
- browser-compat-data 未记录 Firefox for Android 的支持。
- 由 browser-compat-data 镜像自 Firefox 的数据推导。
- browser-compat-data 未记录 Safari 的支持。
- browser-compat-data 未记录 iOS 版 Safari 的支持。
- 由 browser-compat-data 镜像自 Safari 的数据推导。
- 由 browser-compat-data 镜像自 Chrome Android 的数据推导。
- 由 browser-compat-data 镜像自 Chrome Android 的数据推导。