みなさんはスマートフォンをお持ちでしょうか? スマートフォンの普及率も年々拡大し、街を歩いても電車に乗ってもスマートフォンを手にしている人がほとんどです。私はスマートフォン = ユーザーが共通して持っているセンサーの塊だと考えています。今回はHTML5・JavaScriptでそんなセンサーの制御方法をまとめました。本記事のデモは実際にスマートフォンでアクセスするとより楽しめます。

記事内で紹介しているデモのソースコードは、GitHubからダウンロードできます。

アクセスできるアクチュエーター・センサー

JavaScriptで下記のアクチュエーター・センサーから値を取得しコンテンツに反映させる方法を本記事でまとめています。※アクチュエーターとは「駆動装置」という意味です。モーターなどがそれにあたります。

  • バイブレーション
  • GPSセンサー [位置]
  • ジャイロセンサー [傾き]
  • 加速度センサー [慣性]
  • 照度センサー [明るさ]
  • 近接センサー [距離]

バイブレーション

バイブレーションは主にマナーモード時の着信表現として用いられます。端末内のモーターを回転させることで「ブルブルッ」と振動させることができます。HTML5のVibration APIでアクセスできます。残念ながらiOSではサポートされているブラウザはありません。一方のAndroidではChrome・Firefox・標準ブラウザバージョン4.4以降でサポートされています。(2016年5月18日時点)

▲ 灰色の行が現行版バージョンを、緑色になっているものが対応していることを示します。「Can I Use」より

以下にデモを用意しました。サポートされているブラウザで画面をタップすると振動します。

※こちらの動画はXperia Z、Firefoxで撮影しています。

振動させるためには下記のようにJavaScriptでnavigator.vibrate(振動させるミリ秒)メソッドを実行します。配列を指定することで振動パターンを設定することができます。

// 1000ミリ秒振動
navigator.vibrate(1000);

// 500ミリ秒振動して100ミリ秒停止、その後500ミリ秒振動
navigator.vibrate([500, 100, 500]);

GPSセンサー [位置]

GPSは地図アプリやSNSアプリのチェックインなどの位置情報を取得する際に使用されるセンサーです。HTML5のGeolocation APIでアクセスできます。屋内や地下ではGPS信号が届きにくくなるため、ネット回線経由で位置情報を取得します(スマートフォンでの設定が必要です)。iOSのOpera以外でサポートされおりGoogleの検索(「コーヒーショップ」で検索すると周囲のコーヒーショップが地図で表示される)などのさまざまなサービスで使用されています。(2016年5月18日時点)

以下にデモを用意しました。位置情報へのアクセスを許可すると現在いる緯度経度を取得してGoogle Maps上へマーカーを配置します。デモを試していただくとお分かりいただけるかと思いますが、外部環境を受けやすいため完璧な位置を検出することは現状では難しそうです。

位置情報を取得するためには下記のようにJavaScriptでnavigator.geolocation.getCurrentPosition()メソッドに取得成功時に実行したい関数(第1引数)と取得失敗時に実行したい関数(第2引数)を指定します。ここで取得したposition.coords.accuracyパラメーターは緯度経度の誤差を示しており、取得した緯度経度の位置から半径◯m以内に実際の位置があるということを表しています。

// 現在位置の取得
navigator.geolocation.getCurrentPosition(geoSuccess, geoError);
 
// 取得成功
function geoSuccess(position) {
  // 緯度
  const lat = position.coords.latitude;
  // 軽度
  const lng = position.coords.longitude;
  // 緯度経度の誤差(m)
  const accuracy = Math.floor(position.coords.accuracy);
}
 
// 取得失敗(拒否)
function geoError() {
  alert("Geolocation Error")
}

緯度経度以外に高度や方角、速度なども取得できます。(詳しくはHTML5 Geolocation | W3Schoolsをご覧ください)

次のページでは、ジャイロセンサーで傾きと方角を、加速度センサーで慣性を取得する方法を解説します。

ジャイロセンサー [傾き]

シャイロセンサーとは、傾き(回転)を検出するセンサーです。ユーザーがスマートフォンを縦・横のどちらかで使用しているのかを検知してディスプレイを縦・横向きに切り替えるなどの制御を行うために設置されています。HTML5のDeviceOrientation Eventでアクセスできます。下図でサポート状況が黄緑色になっているのは、DeviceOrientationに含まれる方角を取得するCompassNeedsCalibration Eventなどが一部ブラウザでしかサポートされておらず完全サポートには至っていないためです。(2016年5月18日時点)

以下にデモを用意しました。端末を傾けると中央の画像も連動して傾きます。

※こちらの動画はXperia Z、Firefoxで撮影しています。

X・Y・Z軸の値を取得するためには下記のようにJavaScriptでwindowオブジェクトに対してdeviceorientationイベントを監視します。

// DeviceOrientation Event
window.addEventListener("deviceorientation", deviceorientationHandler);
 
// ジャイロセンサーの値が変化
function deviceorientationHandler(event) {
  // X軸
  const beta = event.beta;
  // Y軸
  const gamma = event.gamma;
  // Z軸
  const alpha = event.alpha;
}

ジャイロセンサー [方角]

ジャイロセンサーは傾きの他に方角を取得できます。iOS 5以上のSafariではevent.webkitCompassHeadingパラメーターから取得できますが、その他の環境ではサポートされていません。ジャイロセンサーにアクセスできる全ての環境で方角を取得したい場合は、W3Cの記事「DeviceOrientation Event Specification」にて公開されている、ジャイロセンサーで取得した傾きから方角を算出するロジックを用いることで取得できます。以下のデモでは、そのロジックを使って方位磁石を実装しました。

以下のソースコードで方角を0〜360度の数値で取得します。0度は北、90度は東、180度は南、270度は西となります。

function getCompassHeading(alpha, beta, gamma) {
  const degtorad = Math.PI / 180;
 
  const _x = beta ? beta * degtorad : 0;
  const _y = gamma ? gamma * degtorad : 0;
  const _z = alpha ? alpha * degtorad : 0;
 
  const cY = Math.cos(_y);
  const cZ = Math.cos(_z);
  const sX = Math.sin(_x);
  const sY = Math.sin(_y);
  const sZ = Math.sin(_z);
 
  const Vx = -cZ * sY - sZ * sX * cY;
  const Vy = -sZ * sY + cZ * sX * cY;
 
  let compassHeading = Math.atan(Vx / Vy);
 
  if (Vy < 0) {
    compassHeading += Math.PI;
  }
  else if (Vx < 0) {
    compassHeading += 2 * Math.PI;
  }
 
  return compassHeading * ( 180 / Math.PI );
}

加速度センサー [慣性]

加速度センサーとは、一定時間の間に速度がどの方向にどれだけ変化したかを検出するセンサーです。スマートフォンではXYZの3方向が検出できる3軸加速度センサーが主流となっています。使い道として、スマートフォンが落下して物体に衝突したことなどを検知できます。HTML5のDeviceMotion Eventでアクセスできます。サポート状況は[DeviceOrientation Event]でご紹介した図とおなじになります。

以下にデモを用意しました。スマートフォンを地面に対して垂直に持ち上下左右に振るとその方向へ矢印がアニメーションします。

※こちらの動画はXperia Z、Firefoxで撮影しています。

X・Y・Z軸の値を取得するためには下記のようにJavaScriptでwindowオブジェクトに対してdevicemotionイベントを監視します。

// DeviceMotion Event
window.addEventListener("devicemotion", devicemotionHandler);
 
// 加速度が変化
function devicemotionHandler(event) {
  // 加速度
  // X軸
  const x = event.acceleration.x;
  // Y軸
  const y = event.acceleration.y;
  // Z軸
  const z = event.acceleration.z;
}

次は、照度センサーで周辺の明るさを、近接センサーで検知範囲に物体が存在するか否かを検知する方法を解説します。

照度センサー [明るさ]

照度センサーとは、明るさを検知するセンサーです。屋内・屋外でスマートフォンを使用する際に、環境光にあわせてディスプレイを適切な輝度に調整するために搭載されています。端末によって設置位置が異なりますがディスプレイ上部に設置されていることが多いようです。HTML5のAmbientLight Event でアクセスできます。残念ながらFirefoxのみの対応となっています。(2016年5月18日時点)

以下にデモを用意しました。環境光をルクス(lux)という照度の単位で取得します。明るいほど円が大きくなります。

※こちらの動画はXperia Z、Firefoxで撮影しています。

下記のようにJavaScriptでwindowオブジェクトに対してdevicelightイベントを監視することで照度(0〜)を取得できます。

// AmbientLight Event
window.addEventListener("devicelight", devicelightHandler);
 
// 照度が変化したときのイベント
function devicelightHandler(event) {
  const lux = event.value;
}

近接センサー [距離]

近接センサーとは、検知範囲に物体が存在するか否かを検知できるセンサーです。スマートフォンで電話する際に画面が顔に接近して不意にタップしてしまわないようにディスプレイを一時的にOFFにするなどの制御を行うために設置されています。照度センサーと同じくディスプレイ上部に設置されていることが多いようです。HTML5のProximity Eventでアクセスできます。こちらも[DeviceMotion Event]同様Firefoxのみの対応となっています。(2016年5月18日時点)

以下にデモを用意しました。スマートフォンの近接センサーが設置されている箇所に手をかざすとアニメーションします。

※こちらの動画はXperia Z、Firefoxで撮影しています。

下記のようにJavaScriptでwindowオブジェクトに対してdeviceproximityイベントを監視することで[0 : センサーの検知範囲に物体がある]と[1 : センサーの検知範囲に物体はない]の2パターンの値を取得できます。

// Proximity Event
window.addEventListener("deviceproximity", deviceproximityHandler);
 
// 検知範囲の状況が変化したときのイベント
function deviceproximityHandler(event) {
  if (!event.value) {
    // センサーの検知範囲に物体がある
    showKin();
  } else {
    // センサーの検知範囲に物体はない
    showEn();
  }
}

最後に

多彩なセンサーにアクセスする方法がスマートフォンブラウザでのHTML5に十分に備わっていることは驚きではないでしょうか。

スマートフォンのセンサーを制御するコツとして、センサーから取得した値には誤差があるということを前提に実装を進めるべきです。例えば、GPSセンサーから取得した位置情報をもとに周囲の飲食店を検索するとします。屋内や高層ビル群の中ですとGPSセンサーの通信に影響を与えてしまい実際の位置と誤差が発生してしまうことがあります。ですので「住所」というクリティカルな情報ではなく「◯◯周辺」というざっくりとした情報で検索することが安心かと思います。

Webサイトにこれら多彩なセンサーの制御をアクセントとして取り入れることで、今までに見たことのないコンテンツを作れるかもしれません。ぜひ、ご活用ください。