Sensor APIs - 向 Web 平台公开一致性的设备传感器接口
Sensor API(传感器 API)是根据通用设计构建的一组接口,以一致的方式向 Web 平台公开设备传感器。
传感器 API 的概念和用法
尽管通用的传感器 API 规范定义了一个 Sensor
接口,但作为 Web 开发人员,您不会使用到它。相反,您将使用它的一个子类来检索特定类型的传感器数据。例如,Gyroscope
接口返回设备在读取时沿所有三个轴的加速度。
传感器可能与物理设备传感器完全对应,也可能不完全对应。例如,Gyroscope
接口与物理设备接口完全对应。AbsoluteOrientationSensor
接口则提供从两个或多个设备传感器通过算法聚合的信息。这些传感器类型分别称为低级和高级。后一种类型的传感器也称为融合传感器(或者,虚拟或合成传感器)。
特征检测
传感器接口只是底层设备传感器的代理。因此,传感器的特征检测比其他 API 更复杂。传感器 API 的存在并不能告诉您该 API 是否连接到真正的硬件传感器、该传感器是否工作、它是否仍然连接,甚至用户是否已授予对它的访问权限。使所有这些信息一致可用会对性能和电池寿命造成很大影响。
因此,传感器 API 的功能检测必须包括对 API 本身的检测和防御性编程策略 (见下文)。
下面的实例显示了三种检测传感器 API 的方法。此外,您还可以将对象实例化放在一个 try...catch
块中。请注意,不应该通过 Navigator
接口进行检测。
if (typeof Gyroscope === "function") {
// ...
}
if ("ProximitySensor" in window) {
// ...
}
if (window.AmbientLightSensor) {
// ...
}
防御性编程
如特征检测中所述,检查特定传感器 API 不足以进行特征检测。 还必须确认实际传感器的存在。 这就是需要防御性编程的地方。 防御性编程需要三种策略。
- 检查实例化传感器对象时引发的错误。
- 侦听在使用过程中抛出的错误。
- 优雅地处理错误,从而增强而不是降低用户体验。
下面的代码实例说明了这些原则。try...catch
块捕获传感器实例化期间引发的错误。它侦听 error
事件以捕获在使用过程中引发的错误。只有在需要请求权限以及设备不支持传感器类型时,才会向用户显示内容。
Note: 如果功能策略阻止使用该功能,则原因是您的代码与服务器上设置的策略不一致。该情况不会向用户显示出来。有关实现说明,请参阅
Feature-Policy
。
let accelerometer = null;
try {
accelerometer = new Accelerometer({ referenceFrame: 'device' });
accelerometer.addEventListener('error', event => {
// 处理运行时错误。
if (event.error.name === 'NotAllowedError') {
// 处理用于请求权限的代码。
} else if (event.error.name === 'NotReadableError' ) {
console.log('无法连接到传感器。');
}
});
accelerometer.addEventListener('reading', () => reloadOnShake(accelerometer));
accelerometer.start();
} catch (error) {
// 处理构造错误。
if (error.name === 'SecurityError') {
// 请参阅上面有关功能策略的说明。
console.log('初始化传感器被功能策略阻止。');
} else if (error.name === 'ReferenceError') {
console.log('用户代理不支持传感器。');
} else {
throw error;
}
}
权限和功能策略
除非用户向特定类型的传感器授予许可,否则不能获取传感器数据。请使用 Permissions API 进行操作。下面显示了一个简短的实例,该实例在尝试使用传感器之前请求许可。
navigator.permissions.query({ name: 'accelerometer' })
.then(result => {
if (result.state === 'denied') {
console.log('使用加速度传感器的许可被拒绝。');
return;
}
// 使用传感器。
});
另一种方法是尝试使用传感器并侦听 SecurityError
。
const sensor = new AbsoluteOrientationSensor();
sensor.start();
sensor.addEventListener('error', error => {
if (event.error.name === 'SecurityError')
console.log("没有使用 AbsoluteOrientationSensor 的权限。);
});
下表描述了每种传感器类型、权限 API 所需的名称、<iframe>
元素的 allow
属性和 Feature-Policy
指令。
传感器 | 权限 / 功能策略名称 |
---|---|
AbsoluteOrientationSensor | 'accelerometer' ,'gyroscope' 和 'magnetometer' |
Accelerometer | 'accelerometer' |
AmbientLightSensor | 'ambient-light-sensor' |
GravitySensor | 'accelerometer' |
Gyroscope | 'gyroscope' |
LinearAccelerationSensor | 'accelerometer' |
Magnetometer | 'magnetometer' |
RelativeOrientationSensor | 'accelerometer' 和 'gyroscope' |
读数
传感器读数是通过所有传感器类型继承的 READING
事件回调来接收的。读取频率由您决定,通过将一个选项传递给传感器的构造函数来实现。该选项是一个指定每秒读数的数字。可以使用整数或小数,后者用于频率小于一秒的频率。实际读取频率取决于设备硬件,因此可能小于请求的读取频率。
下面的实例使用 Magneteter
传感器说明了这一点。
let magSensor = new Magnetometer({frequency: 60});
magSensor.addEventListener('reading', e => {
console.log("沿 X 轴方向的磁场:" + magSensor.x);
console.log("沿 Y 轴方向的磁场:" + magSensor.y);
console.log("沿 Z 轴方向的磁场:" + magSensor.z);
})
magSensor.addEventListener('error', event => {
console.log(event.error.name, event.error.message);
})
magSensor.start();
接口
AbsoluteOrientationSensor
安全上下文
描述设备相对于地球参考坐标系的物理方向。
Accelerometer
安全上下文
提供沿所有三个轴应用于设备的加速度。
AmbientLightSensor
安全上下文
返回宿主设备周围环境光的当前灯光级别或照度。
GravitySensor
安全上下文
提供沿所有三个轴应用于设备的重力。
Gyroscope
安全上下文
提供设备沿所有三个轴的角速度。
LinearAccelerationSensor
安全上下文
提供沿所有三个轴应用于设备的加速度,不包含重力的影响。
Magnetometer
安全上下文
提供有关由设备的主磁力计传感器检测到的磁场的信息。
OrientationSensor
安全上下文
AbsolteOrientationSensor
的基类。此接口不能直接使用,它提供了属性和方法用于继承。RelativeOrientationSensor
安全上下文
描述设备的物理方向,不包含地球的参考坐标系。
Sensor
安全上下文
所有其他传感器接口的基类。此接口不能直接使用。相反,它提供用于继承它的接口访问的属性、事件处理程序和方法。
SensorErrorEvent
安全上下文
提供有关由 Sensor
或相关接口引发的错误的信息。
规范
规范 |
---|
Generic Sensor API |
Accelerometer |
Ambient Light Sensor |
Gyroscope |
Magnetometer |
Orientation Sensor |
桌面浏览器兼容性
特性 | Chrome | Edge | Firefox | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|---|
基础支持 | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
activate 事件 | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
activated | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
error 事件 | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
hasReading | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
reading 事件 | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
start | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
stop | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
timestamp | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
移动浏览器兼容性
特性 | Android | Chrome for Android | Edge mobile | Firefox for Android | IE mobile | Opera Android | iOS Safari |
---|---|---|---|---|---|---|---|
基础支持 | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |
activate 事件 | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |
activated | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |
error 事件 | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |
hasReading | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |
reading 事件 | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |
start | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |
stop | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |
timestamp | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |