VIDEO LESSON
JavaScriptのMath.hypot():座標間の距離を計算するの解説動画
再生時間 8:14動画を別のタブで開く ↗
動画の字幕・文字起こしを読む
再生中の字幕を濃い黒で表示し、一番上に追従します。字幕の行を選ぶと、その位置から再生できます。
- 0:00こんにちは。
- 0:01今回はジャバスクリプトのマス・ハイポットを紹介します。
- 0:05画面上の二点がどれだけ離れているか調べたいとき、横の移動量と縦の移動量をそのまま足しても、
- 0:10直線距離にはなりません。
- 0:15例えば横に三、縦に四離れた二点の直線距離は、斜めの辺の長さである五です。
- 0:21この計算は、学校で習う三平方の定理そのものです。
- 0:25マス・ハイポットは、渡された数値をそれぞれ二乗して合計し、その平方根を返します。
- 0:31二点の座標の差を渡せば距離になり、ベクトルの成分を渡せば長さになります。
- 0:38ドラッグの移動量、円形の範囲判定、ゲームの接近判定など、身近な場面で活躍します。
- 0:44自力で二乗と平方根を書く方法と結果は同じですが、この後の章で見るように、
- 0:49大きな値への強さという違いもあります。
- 0:53まず動作環境です。
- 0:55この機能は、二千十五年七月以降、主要ブラウザーで広く使える機能です。
- 1:00現在のクローム、エッジ、ファイアフォックス、サファリなら、追加のライブラリーは不要です。
- 1:07画面要素に依存しない計算だけの処理なので、ブラウザー専用の仕組みを使わず、
- 1:12ノード・ジェイエスでも同じコードが動きます。
- 1:17記事のサンプルはノード・ジェイエス二十二系以降を対象にしていますが、これは記事が採用した条件で、
- 1:23この機能が二十二系で初めて入ったという意味ではありません。
- 1:29古いブラウザーや組み込み環境では、呼び出す前に存在を確認し、なければ処理を止めるのが安全です。
- 1:37基本の書き方を見ましょう。
- 1:39マス・ハイポットに、横方向の差ディーエックスと、縦方向の差ディーワイを渡します。
- 1:46変数名に座標の意味を持たせていますが、この仕組み自体に座標の概念はなく、
- 1:51どの値を渡すかは呼び出す側が決めます。
- 1:56ここで一番の注意点です。
- 1:58二点の距離がほしいときは、座標そのものではなく、差を渡してください。
- 2:04点エーが十と二十、点ビーが十三と二十四なら、差は三と四で、答えは五になります。
- 2:10もし十三と二十四をそのまま渡すと、原点から点ビーまでの距離という、別の計算になってしまいます。
- 2:19どちらの点から測りたいのかを意識して、必ず始点を引いてから渡すクセを付けておきましょう。
- 2:26引数と戻り値の規則を押さえます。
- 2:29引数の個数は決まっておらず、二次元なら二個、三次元なら三個というように、
- 2:33必要な成分だけを渡せます。
- 2:36戻り値は数値で、有限の数を渡した場合はゼロ以上になります。
- 2:41引数が空ならゼロが返り、一個だけ渡すとその絶対値が返ります。
- 2:45先ほどの三次元の例は、二と三と六で、二乗の合計が四と九と三十六で四十九になるため、
- 2:49答えは七です。
- 2:53この処理は同期的で、プロミスは返しません。
- 2:56アウェイトやコールバックは不要です。
- 2:59またマスから直接呼ぶ仕組みなので、ニュー・マスで何かを作る必要もありません。
- 3:04ここからは、入力検証まで含めた完全な例を組み立てます。
- 3:08まずマス・ハイポットが存在するかを確認し、対応していない環境ではそこで止めます。
- 3:14次に、始点と終点の四つの座標を受け取る、ディスタンス・ツーディーという関数を作ります。
- 3:20座標の検証にはナンバー・イズ・ファイナイトを使います。
- 3:24これは文字列を数値へ変換しない判定なので、文字列の三やヌル、ナンや無限大を、
- 3:28座標としてしっかり拒否できます。
- 3:32検証を通ったら座標の差をマス・ハイポットへ渡します。
- 3:35最後に計算結果が有限かどうかも確認し、範囲を超えていればレンジエラーを投げる設計です。
- 3:42作った関数を実行した結果を読みます。
- 3:45十と二十から十三と二十四までの距離は、差の三と四から五になりました。
- 3:50半径六と比較すると、五以下六なので、範囲内を表すトゥルーが返ります。
- 3:55始点と終点が同じ点なら距離はゼロです。
- 3:59三次元の長さは七でした。
- 4:00最後に、意図的に文字列の三を渡すと、検証でタイプエラーが投げられます。
- 4:06これをトライ・キャッチで受け取ることで、処理全体を止めずにエラーの内容だけを表示できます。
- 4:13ここまでの出力は、ノード・ジェイエスの実機でも同じになることを確認済みです。
- 4:20記事の元のサンプルも同じ結果で、計算の流れはこの例と共通しています。
- 4:25失敗しやすい落とし穴です。
- 4:27マス・ハイポット自体は、渡された値を数値へ変換してから計算します。
- 4:32そのため文字列の三を渡しても例外にはならず、五が返ってきます。
- 4:37数値に直せない文字列なら、結果はナンになります。
- 4:41つまり入力が間違っていても、必ずエラーになるとは限らないのです。
- 4:46フォームの入力を扱う場合は、空欄を許すのか、数値の文字列を受け付けるのかを先に決めてから変換してください。
- 4:54先ほどのサンプルが、変換済みの有限な数値だけを受け付ける設計にしたのは、
- 4:58この暗黙の変換に頼らないためです。
- 5:02検証の責任は、呼び出す側にあると覚えておきましょう。
- 5:07特殊な値の扱いも確認します。
- 5:09数値へ変換した結果がナンになると、基本的には結果もナンです。
- 5:14ただし例外があり、引数に正か負の無限大が一つでも含まれると、結果は無限大になります。
- 5:20実際にナンと無限大を一緒に渡すと、返ってくるのはナンではなく無限大です。
- 5:26ナンが含まれていれば必ずナンになる、と思い込んでいると、このケースを見落とします。
- 5:33実務では、入力の段階で有限かどうかを検証しておけば、こうした特殊な値の組み合わせを、
- 5:38計算の後で悩む必要はなくなります。
- 5:42境界のケースほど、検証を前倒しする価値があります。
- 5:46マス・ハイポットを使う大きな理由が、数値の桁あふれへの強さです。
- 5:52自力で二乗して平方根を求める書き方だと、最終的な答えは表現できる範囲内でも、
- 5:59途中の二乗が大きくなりすぎて無限大になってしまうことがあります。
- 6:06例えば一の後にゼロが二百個続くような大きな数では、その二乗自体が範囲を超えます。
- 6:13しかしマス・ハイポットに同じ数を二つ渡すと、約一・四一四二かける十の二百乗という正しい答えが返ります。
- 6:23逆に極端に小さい値の二乗がゼロになってしまう問題も避けられます。
- 6:29ただし、座標の差を求める引き算自体が先にあふれた場合は救えないので、結果の検証は引き続き大切です。
- 6:38活用場面を見ましょう。
- 6:40円形の操作範囲では、中心から対象までの距離と半径を比べます。
- 6:45以下、と書けば円周上の点も範囲内になり、未満に変えれば円周を除外できます。
- 6:51ドラッグ操作では、開始位置から現在位置までの距離を調べ、一定の距離を超えた時点でドラッグ開始と判断する使い方ができます。
- 7:01その際、両方の座標を同じ基準にそろえることが大切です。
- 7:05画面基準とページ基準を混ぜると、計算はできても意味の違う距離になります。
- 7:11なお、緯度と経度をそのまま渡して地球上の距離を求める用途には適しません。
- 7:17座標系と単位に合った計算方法を選んでください。
- 7:21制約とまとめです。
- 7:23マス・ハイポットは大きな値や小さな値に強い計算ですが、浮動小数点の丸め誤差まで消えるわけではありません。
- 7:32ちょうど境界線上かどうかを判定する場面では、用途に応じた許容差を設けてください。
- 7:38また実務で使うなら、まず入力の単位と許容範囲を決めることが近道です。
- 7:44画面のピクセルでも、ゲーム内の座標でも、計測値でも、呼び出す側で単位と座標系をそろえておけば、
- 7:50短い距離計算の関数を安全に使い回せます。
- 7:56二点の距離に迷ったら、差を取ってマス・ハイポットへ渡す。
- 8:01この流れを、検証とセットでぜひ活用してください。
- 8:05まずはコンソールで三と四を渡して五が返ることを確かめるところから始めてみてください。
- 8:12お疲れさまでした。
この動画で学べること
Math.hypot()で座標間の距離やベクトルの長さを求める方法を解説。ブラウザーとNode.jsの実行手順、引数・戻り値、入力検証、数値計算の制約をコードで学べます。
解説記事・サンプルコードを読む:JavaScriptのMath.hypot():座標間の距離を計算する →