Sensor APIs
传感器 API 是一组接口,它们基于通用设计构建,以一致的方式将设备传感器暴露给 Web 平台。
概念与用法
尽管通用传感器 API 规范定义了一个 Sensor 接口,但作为 Web 开发者,您永远不会直接使用它。相反,您将使用它的某个子类来检索特定类型的传感器数据。例如,Accelerometer 接口返回设备在读取时沿三个轴的加速度。
传感器可能对应也可能不完全对应物理设备传感器。例如,Gyroscope 接口完全对应一个物理设备接口。或者,AbsoluteOrientationSensor 接口提供的信息是根据两个或多个设备传感器算法聚合而成的。这些传感器类型分别被称为低级和高级。后一种类型的传感器也称为融合传感器(或虚拟传感器、合成传感器)。
特性检测
传感器接口只是底层设备传感器的代理。因此,传感器比其他 API 更难进行特性检测。传感器 API 的存在并不能告诉您该 API 是否连接到真实硬件传感器、该传感器是否正常工作、是否仍然连接,甚至用户是否已授予对其的访问权限。一致地提供所有这些信息会影响性能和电池续航。
因此,传感器 API 的特性检测必须同时包括 API 本身的检测以及 防御性编程策略(见下文)。
下面的示例演示了检测传感器 API 的三种方法。此外,您还可以将对象实例化放在 try...catch 块中。请注意,通过 Navigator 接口进行检测不是可用选项之一。
if (typeof Gyroscope === "function") {
// run in circles…
}
if ("ProximitySensor" in window) {
// watch out!
}
if (window.AmbientLightSensor) {
// go dark…
}
防御性编程
如特性检测中所述,仅检查特定传感器 API 不足以进行特性检测。还必须确认实际传感器的存在。这时就需要防御性编程。防御性编程需要三种策略。
- 检查实例化传感器对象时抛出的错误。
- 监听使用过程中抛出的错误。
- 优雅地处理错误,从而提升而非降低用户体验。
下面的代码示例说明了这些原则。try...catch 块捕获传感器实例化期间抛出的错误。它监听 error 事件以捕获使用过程中抛出的错误。只有在需要请求 权限 以及设备不支持该传感器类型时,才会向用户显示内容。
此外,此功能可能会被服务器设置的 权限策略 阻止。
let accelerometer = null;
try {
accelerometer = new Accelerometer({ referenceFrame: "device" });
accelerometer.addEventListener("error", (event) => {
// Handle runtime errors.
if (event.error.name === "NotAllowedError") {
// Branch to code for requesting permission.
} else if (event.error.name === "NotReadableError") {
console.log("Cannot connect to the sensor.");
}
});
accelerometer.addEventListener("reading", () => reloadOnShake(accelerometer));
accelerometer.start();
} catch (error) {
// Handle construction errors.
if (error.name === "SecurityError") {
// See the note above about permissions policy.
console.log("Sensor construction was blocked by a permissions policy.");
} else if (error.name === "ReferenceError") {
console.log("Sensor is not supported by the User Agent.");
} else {
throw error;
}
}
权限和权限策略
除非用户使用 权限 API 授予对特定传感器类型的权限,并且/或者访问未被服务器 Permissions-Policy 阻止,否则可能无法读取传感器。
下面的示例展示了如何在尝试使用传感器之前请求用户权限。
navigator.permissions.query({ name: "accelerometer" }).then((result) => {
if (result.state === "denied") {
console.log("Permission to use accelerometer sensor is denied.");
return;
}
// Use the sensor.
});
另一种方法是尝试使用传感器并监听 SecurityError。
const sensor = new AbsoluteOrientationSensor();
sensor.start();
sensor.addEventListener("error", (error) => {
if (event.error.name === "SecurityError")
console.log("No permissions to use AbsoluteOrientationSensor.");
});
下表描述了每种传感器类型所需的权限 API 名称、<iframe> 元素的 allow 属性以及 Permissions-Policy 指令。
| Sensor | 权限策略名称 |
|---|---|
AbsoluteOrientationSensor |
'accelerometer'、'gyroscope' 和 'magnetometer' |
加速度计 |
'accelerometer' |
环境光传感器 |
'ambient-light-sensor' |
GravitySensor |
'accelerometer' |
Gyroscope |
'gyroscope' |
LinearAccelerationSensor |
'accelerometer' |
磁力计 |
'magnetometer' |
RelativeOrientationSensor |
'accelerometer' 和 'gyroscope' |
读数
传感器读数通过所有传感器类型继承的 reading 事件回调接收。读数频率由您决定,通过传递给传感器构造函数的选项来实现。该选项是一个数字,指定每秒的读数次数。可以使用整数或小数,后者用于每秒频率低于 1 的情况。实际读数频率取决于设备硬件,因此可能低于请求的频率。
以下示例使用 Magnetometer 传感器说明了这一点。
let magSensor = new Magnetometer({ frequency: 60 });
magSensor.addEventListener("reading", (e) => {
console.log(`Magnetic field along the X-axis ${magSensor.x}`);
console.log(`Magnetic field along the Y-axis ${magSensor.y}`);
console.log(`Magnetic field along the Z-axis ${magSensor.z}`);
});
magSensor.addEventListener("error", (event) => {
console.log(event.error.name, event.error.message);
});
magSensor.start();
接口
AbsoluteOrientationSensor-
描述设备相对于地球参考坐标系统的物理方向。
加速度计-
提供设备沿三个轴施加的加速度。
环境光传感器-
返回托管设备周围环境光的当前光照级别或照度。
GravitySensor-
提供设备沿三个轴施加的重力。
Gyroscope-
提供设备沿三个轴的角速度。
LinearAccelerationSensor-
提供设备沿三个轴施加的加速度,但不包含重力的贡献。
磁力计-
提供设备主要磁力计传感器检测到的有关磁场的信息。
OrientationSensor-
AbsoluteOrientationSensor的基类。此接口不能直接使用,而是提供由继承它的接口访问的属性和方法。 RelativeOrientationSensor-
描述设备相对于地球参考坐标系统的物理方向。
Sensor-
所有其他传感器接口的基类。此接口不能直接使用。相反,它提供了由继承它的接口访问的属性、事件处理程序和方法。
SensorErrorEvent-
提供有关
Sensor或相关接口抛出的错误的信息。
规范
| 规范 |
|---|
| 通用传感器 API |
| 加速度计 |
| 方向传感器 |
| 环境光传感器 |
| Gyroscope |
| 磁力计 |
浏览器兼容性
api.Sensor
加载中…
api.Accelerometer
加载中…
api.OrientationSensor
加载中…
api.Gyroscope
加载中…
api.Magnetometer
加载中…
api.AmbientLightSensor
加载中…