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
載入中…