JavaScriptのMath.atan2():2点間の方向を角度に変換する
Math.atan2()で2点間の方向を角度に変換する方法を解説。引数・戻り値、ブラウザーとNode.jsの実行手順、画面座標の扱い、同一点や不正入力への対応を学べます。
目的:位置の差から向きを求める
ゲームでキャラクターを目標へ向けるときや、配置図で接続先への矢印を描くときには、2点の位置から方向を求める必要があります。右上、左下といった条件分岐を並べる代わりに、方向を角度として取り出せるのがMath.atan2()です。
例えば、出発点から右へ10、上へ10進む方向は45度です。左へ10、上へ10なら135度になります。横方向と縦方向の比率が同じでも、符号が変われば向きも変わります。この符号まで含めて扱えるため、全方向をまとめて計算できます。
この記事では、右を0度、上を90度とする数学の座標を基準にします。そのうえで、ブラウザーの画面座標へ応用するときの注意点を確認します。
動作環境と対応バージョン
Math.atan2()はJavaScript標準の組み込みメソッドで、ブラウザーとNode.jsの両方で利用できます。DOMや外部ライブラリーには依存せず、インポートも不要です。
2026年10月22日時点で確認したMDNのMath.atan2()では、2015年7月からブラウザー間で広く利用できる機能とされています。現在のChrome、Edge、Firefox、Safariを対象にできます。この日付は各ブラウザーの初回実装日を意味しません。
以下のサンプルは、ブラウザーの現行版、またはNode.js 22以降を実行環境として想定します。これはサンプルの対象バージョンであり、Math.atan2()がNode.js 22で追加されたという意味ではありません。サンプルではconstやNumber.isFinite()も使うため、メソッド単体の古い対応範囲とコード全体の対応範囲を分けて考えてください。
引数と戻り値
呼び出し方はMath.atan2(y, x)です。座標を普段書く順番とは逆に、縦方向のyを先に渡します。
- 第1引数の
yは縦方向の成分です。 - 第2引数の
xは横方向の成分です。 - 戻り値は
number型の角度で、単位はラジアンです。 - 戻り値の範囲は
-Math.PI以上、Math.PI以下です。
通常の数学座標では、正の横軸から反時計回りに測った角度を返します。度数法に変えるには、戻り値に180 / Math.PIを掛けます。この定義と引数順はMDNの引数・戻り値の説明で確認できます。
2点を扱うときは差分を渡す
出発点をfrom、到着点をtoとすると、必要なのは到着点そのものの座標ではなく、出発点からの差分です。
const from = { x: 20, y: 30 };
const to = { x: 30, y: 40 };
const dx = to.x - from.x;
const dy = to.y - from.y;
const degrees = Math.atan2(dy, dx) * 180 / Math.PI;
console.log(degrees.toFixed(1));期待出力は次のとおりです。
45.0両方の点を同じだけ移動させても差分は変わりません。そのため、原点から離れた場所でも同じ考え方で方向を求められます。
コピーして実行できる完成例
次のコードは入力検証を含む自己完結した例です。関数directionDegrees()は4個の座標値を受け取り、方向を度数法で返します。同じ位置どうしには方向を定められないため、nullを返す設計にしています。
(() => {
"use strict";
function directionDegrees(fromX, fromY, toX, toY) {
const coordinates = [fromX, fromY, toX, toY];
if (!coordinates.every(Number.isFinite)) {
throw new TypeError("座標には有限の数値を指定してください");
}
const dx = toX - fromX;
const dy = toY - fromY;
if (!Number.isFinite(dx) || !Number.isFinite(dy)) {
throw new RangeError("座標の差分が数値の範囲を超えています");
}
if (dx === 0 && dy === 0) {
return null;
}
return Math.atan2(dy, dx) * 180 / Math.PI;
}
const cases = [
["右", 10, 20, 20, 20],
["上", 10, 20, 10, 30],
["左上", 10, 20, 0, 30],
["下", 10, 20, 10, 10],
["同一点", 10, 20, 10, 20]
];
for (const [label, ...coordinates] of cases) {
const angle = directionDegrees(...coordinates);
const result = angle === null ? "方向なし" : `${angle.toFixed(1)}度`;
console.log(`${label}: ${result}`);
}
try {
directionDegrees(0, 0, "10", 10);
} catch (error) {
console.log(`入力エラー: ${error.message}`);
}
})();ブラウザーでの実行方法
Chromeなどで空のタブを開き、開発者ツールのConsoleを表示します。コードブロック内のJavaScript全体を入力して実行してください。HTMLファイルやローカルサーバーの準備は不要です。
全体を即時実行関数で囲んでいるため、Consoleで繰り返し実行しても、サンプルの変数名がトップレベルに残りません。Consoleが表示する評価結果のundefinedは、サンプルが出力した行とは別です。
Node.jsでの実行方法
Node.js 22以降を用意し、コード全体をUTF-8のdirection.jsとして保存します。ターミナルでそのファイルがあるフォルダーへ移動し、次のコマンドを実行します。
node direction.jsパッケージのインストールやpackage.jsonの作成は不要です。ファイル名をnodeに渡す実行方法はNode.js公式のスクリプト実行ガイドでも説明されています。
期待出力と処理の確認
両方の環境で、次のログを想定しています。実機で実行した結果ではなく、コードと仕様から確認した期待出力です。
右: 0.0度
上: 90.0度
左上: 135.0度
下: -90.0度
同一点: 方向なし
入力エラー: 座標には有限の数値を指定してください最後の呼び出しでは、数値ではなく文字列の"10"を渡しています。入力検証で例外を投げ、呼び出し側のtry...catchで受け取るため、処理が未処理例外で終了することを防いでいます。すべて同期処理なので、Promiseやawaitは不要です。
失敗例と制約
引数を逆にすると別の方向になる
Math.atan2(dx, dy)と書くと、横と縦を交換した方向を計算してしまいます。特に右上45度の例では、交換しても結果が同じなので誤りを見落とします。確認には、右だけ、上だけ、左上など、複数の方向を使ってください。
また、比率を先に計算するMath.atan(dy / dx)への置き換えでは、左右を区別する情報が失われます。例えば左上の差分dx = -10、dy = 10では、必要な135度を求められません。縦と横を別々に渡すことに意味があります。
同一点と不正入力を区別する
組み込みのMath.atan2(0, 0)は0を返します。しかし、アプリケーションで同一点を「右向き」と扱うと、目標に到着した瞬間に矢印が右を向くことがあります。完成例がnullを返すのは、この問題を避けるための独自ルールです。
組み込みメソッドには符号付きゼロや無限大に対する定義もありますが、完成例では有限の座標だけを受け付けます。有限値どうしでも、極端に大きな値の引き算は無限大になる可能性があるため、差分も検証しています。
MathはBigInt用のAPIではありません。また、一般の角度計算では浮動小数点の誤差を考慮し、小数の完全一致を判定条件にしないでください。toFixed(1)は表示用の文字列を作る処理なので、計算には丸める前の値を残します。MDNのMath解説も、数値型と実装ごとの精度について説明しています。
活用事例と設計の改善案
配置図の矢印、ゲーム内の照準、経路上の移動方向など、平面上の2点を結ぶ向きを求める場面に使えます。サーバー側で方向を計算し、ブラウザーへ数値として渡す構成にもできます。
ブラウザーの一般的な画面座標では、縦座標は下へ行くほど増えます。同じ差分計算を使うと、画面上では下が正の90度になります。数学座標と同じく上を正にしたいなら、縦の差分をfromY - toYへ変更してください。どちらを使うかは、角度を受け取る描画処理の規則に合わせます。
実装を改善するなら、最初に「右が0度か」「正方向は時計回りか」「同一点で向きを維持するか」を決め、関数の説明に残すことを勧めます。例えば同一点でnullが返ったら、画面側は直前の向きを維持できます。方向の計算と表示の判断を分けると、到着時の挙動を変更しやすくなります。
なお、この計算は平面用です。緯度・経度をそのまま渡して地球上の正確な進行方位を求める用途には使えません。
公式参考資料
Googleの優先するニュース提供元にSEの部屋を追加
Googleで、いつも読みたい情報源を選べます。登録可否はGoogleの画面で確認できます。
候補にSEの部屋が表示されない場合は、まだ追加できません。