Sensor APIs

Sensor APIs は、デバイスのセンサーを一貫した形でウェブプラットフォームから利用可能にする、共通の設計で作られたインターフェイスの集合です。

Sensor APIs の概念と使用法

Generic Sensor API の仕様では Sensor インターフェイスが定義されていますが、ウェブ開発者がこれを用いることはないでしょう。かわりに、特定の種類のセンサーからデータを取得するために、そのサブクラスを用いることになります。たとえば、Accelerometer インターフェイスは取得時にデバイスの 3 軸それぞれにかかっている加速度を返します。

センサーは、デバイスの物理的なセンサーに完全に対応していることも、対応していないこともあります。たとえば、Gyroscope インターフェイスはデバイスの物理的なインターフェイスに完全に対応しています。一方、AbsoluteOrientationSensor インターフェイスは 2 個以上のデバイスセンサーの情報をアルゴリズムにより組み合わせた情報を提供します。これらのセンサーの種類は、それぞれ 低レベル および 高レベル と呼ばれます。後者の種類のセンサーは、フュージョンセンサー (または、仮想センサー、合成センサー) とも呼ばれます。

機能の検出

センサーインターフェイスは、対応するデバイスセンサーのプロキシーでしかありません。そのため、センサーの機能の検出は他の API より複雑になります。センサー API が存在するからといって、API が実際のハードウェアセンサーに接続されているか、センサーが動作するか、センサーの接続が維持されているか、ユーザーがセンサーへのアクセスを許可したかはわかりません。これらすべての情報を常に利用可能にしておくことは、パフォーマンスと電池の持ちに負担をかけます。

そのため、センサー API の機能を検出するには、API そのものを検出した上で、防衛的プログラミングの戦略 (後述) をとらなければいけません。

以下の例では、センサー API を検出する 3 通りの方法を示します。さらに、オブジェクトの生成を try...catch ブロックの中で行う方法もあります。なお、Navigator インターフェイスを用いた検出は利用可能な選択肢に含まれないことに注意してください。

js
if (typeof Gyroscope === "function") {
  // ぐるぐる回る…
}

if ("ProximitySensor" in window) {
  // 注意!
}

if (window.AmbientLightSensor) {
  // 暗闇へ…
}

防衛的プログラミング

機能の検出の節で言及したように、特定のセンサー API が使えるかをチェックするだけでは機能の検出には不十分です。実際のセンサーが存在することも確認しなければいけません。このために防衛的プログラミングが必要です。防衛的プログラミングには、3 個の戦略が必要です。

  • センサーオブジェクトを生成するとき、投げられるエラーをチェックする。
  • 使用時に投げられるエラーを監視する。
  • エラーをきれいに処理し、ユーザー体験が損なわれず拡充されるようにする。

以下のコード例で、これらの原則を説明します。try...catch ブロックにより、センサーの生成時に投げられるエラーをキャッチします。error イベントを監視することで、使用時に投げられるエラーをキャッチします。ユーザーに何かが提示されるのは、許可の要求が必要なときと、デバイスがこのセンサーの種類に対応していないときだけです。

さらに、この機能はサーバーで設定された Permissions Policy によりブロックされる可能性があります。

js
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") {
    // 前述の Permissions Policy に関するメモを参照
    console.log(
      "センサーの生成が Permissions Policy によりブロックされました。",
    );
  } else if (error.name === "ReferenceError") {
    console.log("このユーザーエージェントはセンサーに対応していません。");
  } else {
    throw error;
  }
}

許可と Permissions Policy

センサーの計測値は、Permissions API によりユーザーが特定のセンサーの種類を用いる許可を与え、かつサーバーの Permissions-Policy でブロックされていない場合のみ参照できます。

以下の例では、センサーを使用しようとする前にユーザーに許可を要求する方法を示します。

js
navigator.permissions.query({ name: "accelerometer" }).then((result) => {
  if (result.state === "denied") {
    console.log("加速度計センサーを使う許可が得られませんでした。");
    return;
  }
  // センサーを使用する
});

別の方法として、センサーを使用しようとして、SecurityError を監視することもできます。

js
const sensor = new AbsoluteOrientationSensor();
sensor.start();
sensor.addEventListener("error", (error) => {
  if (event.error.name === "SecurityError")
    console.log("AbsoluteOrientationSensor を使用する許可がありません。");
});

以下の表では、それぞれのセンサーの種類について、Permissions API、<iframe> 要素の allow 属性、Permissions-Policy ディレクティブで必要な名前を示します。

センサー Permission Policy 名
AbsoluteOrientationSensor 'accelerometer''gyroscope''magnetometer'
Accelerometer 'accelerometer'
AmbientLightSensor 'ambient-light-sensor'
GravitySensor 'accelerometer'
Gyroscope 'gyroscope'
LinearAccelerationSensor 'accelerometer'
Magnetometer 'magnetometer'
RelativeOrientationSensor 'accelerometer''gyroscope'

計測値

センサーの計測値は、すべてのセンサーの種類で継承されている reading イベントコールバックを通じて取得できます。取得の頻度はセンサーのコンストラクターに渡すオプションで使用者が設定します。このオプションは、1 秒あたり何回取得するかを表す数値です。整数または小数を使用することができ、小数は 1 秒に 1 回未満の頻度を設定するとき用います。実際の取得頻度はデバイスのハードウェアに依存し、設定より少なくなる可能性があります。

以下の例では、Magnetometer センサーを用いてこれを説明します。

js
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 安全なコンテキスト用

デバイスの 3 軸それぞれにかかっている加速度を提供します。

AmbientLightSensor 安全なコンテキスト用

現在の光レベル、すなわちホストデバイスの周囲の環境光の照度を返します。

GravitySensor 安全なコンテキスト用

デバイスの 3 軸それぞれにかかっている重力を提供します。

Gyroscope 安全なコンテキスト用

デバイスの 3 軸それぞれの角速度を提供します。

LinearAccelerationSensor 安全なコンテキスト用

デバイスの 3 軸それぞれにかかっている加速度を、重力の影響を除いて提供します。

Magnetometer 安全なコンテキスト用

デバイスのプライマリー磁気センサーで検出される磁場の情報を提供します。

OrientationSensor 安全なコンテキスト用

AbsoluteOrientationSensor のベースクラスです。このインターフェイスを直接用いることはできませんが、継承するインターフェイスがアクセスするプロパティとメソッドを提供します。

RelativeOrientationSensor 安全なコンテキスト用

地球の参照用座標系は考慮せず、デバイスの物理的な向きを表します。

Sensor 安全なコンテキスト用

他のセンサーインターフェイスすべてのベースクラスです。このインターフェイスを直接用いることはできませんが、継承するインターフェイスがアクセスするプロパティ・イベントハンドラー・メソッドを提供します。

SensorErrorEvent 安全なコンテキスト用

Sensor や関連するインターフェイスから投げられたエラーの情報を提供します。

仕様書

Specification
Generic Sensor API
Accelerometer
Orientation Sensor
Ambient Light Sensor
Gyroscope
Magnetometer

ブラウザーの互換性

api.Sensor

BCD tables only load in the browser

api.Accelerometer

BCD tables only load in the browser

api.OrientationSensor

BCD tables only load in the browser

api.Gyroscope

BCD tables only load in the browser

api.Magnetometer

BCD tables only load in the browser

api.AmbientLightSensor

BCD tables only load in the browser