JavaScript | Web API:位置情報・センサー - DeviceOrientation

JavaScript JavaScript
スポンサーリンク

DeviceOrientation は「端末がどっち向いているか」を教えてくれるセンサー

まずイメージからいきます。

DeviceOrientation は、
スマホやタブレットの「向き」を教えてくれる仕組みです。

端末を左右に傾ける
前後に傾ける
くるっと回転させる(コンパスのように向きを変える)

こういう動きを、JavaScript から数値として受け取れます。

ゲームで「端末を傾けて操作する」
AR っぽく「端末の向きで画面の表示を変える」
コンパス風に「北の方向を表示する」

こういう表現の土台になるのが DeviceOrientation です。


DeviceOrientationEvent の基本イメージ

「イベントとして向きが流れてくる」

DeviceOrientation は、関数を呼んで値をもらうのではなく、
「イベント」として向きの情報が流れてきます。

基本形はこうです。

window.addEventListener("deviceorientation", (event) => {
  console.log(event.alpha, event.beta, event.gamma);
});
JavaScript

deviceorientation イベントが発生するたびに、
コールバックが呼ばれます。

ここで渡される event の中に、
端末の向きを表す 3 つの角度が入っています。

alpha
beta
gamma

この 3 つをどうイメージするかが、最初の山です。


alpha / beta / gamma をざっくりイメージで掴む

beta: 前後の傾き(うなずく動き)

beta は、端末を「前後」に傾けた角度です。

スマホを顔の前に立てて持っている状態から、
前に倒す・後ろに倒す、あの動きです。

ざっくりイメージはこんな感じです。

画面を上に向けて机に置く → beta ≒ 90
画面を正面に向けて立てて持つ → beta ≒ 0
画面を下に向けて伏せる → beta ≒ −90

「うなずく」「のけぞる」方向の傾きだと思ってください。

gamma: 左右の傾き(首をかしげる動き)

gamma は、端末を「左右」に傾けた角度です。

スマホを正面に向けて持った状態から、
左に傾ける・右に傾ける、あの動きです。

ざっくりイメージはこうです。

左に傾ける → gamma はマイナス方向
右に傾ける → gamma はプラス方向

「首をかしげる」ような左右の傾きだと思うと分かりやすいです。

alpha: 端末の向き(コンパス的な回転)

alpha は、端末を「平面上で回転させた角度」です。

スマホを机の上に置いて、
くるっと回すときの回転です。

ざっくりイメージはこうです。

北を向いているとき → alpha ≒ 0
東を向いているとき → alpha ≒ 90
南を向いているとき → alpha ≒ 180
西を向いているとき → alpha ≒ 270

ただし、実際の値はブラウザや端末によって少し違ったり、
「絶対方位(地磁気)」を使うかどうかで変わったりします。

最初は「端末を回すと alpha が変わる」くらいの感覚で十分です。


まずは「傾きで四角を動かす」簡単な例から

HTML と CSS

<div id="area">
  <div id="box"></div>
</div>
<p id="info">端末を傾けてみてください</p>
#area {
  width: 300px;
  height: 300px;
  border: 1px solid #ccc;
  margin: 20px auto;
  position: relative;
  overflow: hidden;
}

#box {
  width: 30px;
  height: 30px;
  background: tomato;
  position: absolute;
  left: 135px;
  top: 135px;
}

JavaScript(beta / gamma で位置を変える)

const area = document.querySelector("#area");
const box = document.querySelector("#box");
const info = document.querySelector("#info");

let centerX = area.clientWidth / 2;
let centerY = area.clientHeight / 2;

function handleOrientation(event) {
  const beta = event.beta;   // 前後の傾き
  const gamma = event.gamma; // 左右の傾き

  const maxOffsetX = area.clientWidth / 2 - box.clientWidth / 2;
  const maxOffsetY = area.clientHeight / 2 - box.clientHeight / 2;

  const x = (gamma / 45) * maxOffsetX;
  const y = (beta / 45) * maxOffsetY;

  box.style.left = `${centerX + x - box.clientWidth / 2}px`;
  box.style.top = `${centerY + y - box.clientHeight / 2}px`;

  info.textContent =
    `beta(前後): ${beta?.toFixed(1)} / gamma(左右): ${gamma?.toFixed(1)}`;
}

window.addEventListener("deviceorientation", handleOrientation);
JavaScript

このコードでやっていることを日本語にすると、

端末の前後・左右の傾き(beta / gamma)を受け取る
その値を「エリアの中心からのオフセット」に変換する
四角の位置をそのオフセットだけ動かす

という流れです。

実際にスマホで開いてみると、
端末を傾けると四角がスーッと動いてくれます。

「数値としての beta / gamma」が、
「画面上の動き」に変わる瞬間を体感してほしいです。


iOS Safari での「権限」がちょっとクセ者

いきなり動かないことがある理由

最近の iOS(iPhone / iPad)では、
DeviceOrientation を使うときに「ユーザーの許可」が必要です。

そのため、単に

window.addEventListener("deviceorientation", handler);
JavaScript

と書いただけでは、
イベントが飛んでこないことがあります。

iOS では、ユーザーの操作(タップなど)をきっかけに
「モーションと方向のアクセスを許可しますか?」
というダイアログを出して、許可をもらう必要があります。

iOS での許可リクエストの例

const btn = document.querySelector("#requestBtn");
const info = document.querySelector("#info");

btn.addEventListener("click", async () => {
  if (
    typeof DeviceOrientationEvent !== "undefined" &&
    typeof DeviceOrientationEvent.requestPermission === "function"
  ) {
    try {
      const state = await DeviceOrientationEvent.requestPermission();
      if (state === "granted") {
        info.textContent = "センサーの利用が許可されました。端末を傾けてみてください。";
        window.addEventListener("deviceorientation", handleOrientation);
      } else {
        info.textContent = "センサーの利用が拒否されました。";
      }
    } catch (e) {
      info.textContent = "センサーの権限リクエストに失敗しました。";
    }
  } else {
    info.textContent = "このブラウザは iOS の権限リクエスト API に対応していません。";
    window.addEventListener("deviceorientation", handleOrientation);
  }
});
JavaScript

ポイントは、

ユーザーのタップをトリガーに requestPermission() を呼ぶ
granted のときだけ deviceorientation を監視し始める

という流れにしていることです。

「権限管理」の話とつながりますが、
センサー系も「勝手に使わない」「ちゃんと説明してから使う」が基本です。


alpha を使って「なんちゃってコンパス」を作る

端末の向きで針を回すイメージ

alpha は「端末の回転(向き)」なので、
これをそのまま CSS の回転に使うと、
コンパスっぽい表現が作れます。

HTML:

<div id="compass">
  <div id="needle"></div>
</div>
<p id="angleInfo">端末を回してみてください</p>

CSS(超シンプル版):

#compass {
  width: 150px;
  height: 150px;
  border-radius: 50%;
  border: 2px solid #333;
  margin: 20px auto;
  position: relative;
}

#needle {
  width: 4px;
  height: 70px;
  background: red;
  position: absolute;
  left: 50%;
  top: 5px;
  transform-origin: 50% 90%;
}

JavaScript:

const needle = document.querySelector("#needle");
const angleInfo = document.querySelector("#angleInfo");

function handleOrientation(event) {
  const alpha = event.alpha; // 0〜360 の角度(端末の回転)

  if (alpha == null) {
    angleInfo.textContent = "alpha が取得できません";
    return;
  }

  const angle = 360 - alpha;

  needle.style.transform = `translateX(-50%) rotate(${angle}deg)`;
  angleInfo.textContent = `alpha: ${alpha.toFixed(1)}°`;
}

window.addEventListener("deviceorientation", handleOrientation);
JavaScript

ここでは、

端末の回転角(alpha)を受け取る
針の CSS transform にその角度を反映する

というだけのシンプルな処理です。

実際には「真北」に合わせるにはもう少し工夫が必要ですが、
「端末を回すと針が回る」という体験だけでも、
DeviceOrientation の楽しさがかなり伝わるはずです。


DeviceOrientation を使うときに意識してほしいポイント

端末依存・ブラウザ依存が強い

DeviceOrientation は、
PC ではそもそもセンサーがないことが多いですし、
ブラウザによって挙動や値の意味が微妙に違うこともあります。

だからこそ、

スマホ前提の機能として設計する
PC では「この機能は利用できません」と案内する
値の範囲や向きは実機で確認する

といった割り切りが必要です。

値は「ノイズがある」「揺れる」前提で扱う

センサー値は、位置情報と同じで「完璧」ではありません。

端末をじっと固定していても、
alpha / beta / gamma が少しずつ揺れることがあります。

ゲームなどで使うときは、

値を少し丸める(小数点以下を切り捨てる)
急激な変化をフィルタリングする

といった工夫を入れると、
動きが落ち着いて見えます。


初心者として「DeviceOrientation」で掴んでほしいこと

DeviceOrientation の本質は、
「端末の向き(回転・傾き)をリアルタイムにイベントとして受け取る」
ということです。

そのうえで、まずこの感覚を持っておいてほしいです。

deviceorientation イベントで alpha / beta / gamma が飛んでくる
beta は前後の傾き、gamma は左右の傾き、alpha は回転の向き
傾きの値を「画面上の位置や回転」に変換すると、直感的な UI が作れる
iOS ではユーザーの許可(requestPermission)が必要になることがある

練習としては、

beta / gamma で四角を動かす
alpha で針を回す「なんちゃってコンパス」を作る

この 2 つを自分の手で書いてみると、
「センサーの数値」と「画面の動き」が頭の中でつながります。

そこまで行くと、
「端末を傾けて操作するゲーム」
「向きによって表示が変わるインタラクション」

みたいなアイデアが、
「自分でも作れそうなもの」に変わってきます。

タイトルとURLをコピーしました