DeviceOrientation は「端末がどっち向いているか」を教えてくれるセンサー
まずイメージからいきます。
DeviceOrientation は、
スマホやタブレットの「向き」を教えてくれる仕組みです。
端末を左右に傾ける
前後に傾ける
くるっと回転させる(コンパスのように向きを変える)
こういう動きを、JavaScript から数値として受け取れます。
ゲームで「端末を傾けて操作する」
AR っぽく「端末の向きで画面の表示を変える」
コンパス風に「北の方向を表示する」
こういう表現の土台になるのが DeviceOrientation です。
DeviceOrientationEvent の基本イメージ
「イベントとして向きが流れてくる」
DeviceOrientation は、関数を呼んで値をもらうのではなく、
「イベント」として向きの情報が流れてきます。
基本形はこうです。
window.addEventListener("deviceorientation", (event) => {
console.log(event.alpha, event.beta, event.gamma);
});
JavaScriptdeviceorientation イベントが発生するたびに、
コールバックが呼ばれます。
ここで渡される 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 つを自分の手で書いてみると、
「センサーの数値」と「画面の動き」が頭の中でつながります。
そこまで行くと、
「端末を傾けて操作するゲーム」
「向きによって表示が変わるインタラクション」
みたいなアイデアが、
「自分でも作れそうなもの」に変わってきます。
