WEBVTT

1
00:00:00.000 --> 00:00:01.009
こんにちは。

2
00:00:01.009 --> 00:00:05.549
今回はジャバスクリプトのマス・ハイポットを紹介します。

3
00:00:05.549 --> 00:00:10.342
画面上の二点がどれだけ離れているか調べたいとき、横の移動量と縦の移動量をそのまま足しても、

4
00:00:10.342 --> 00:00:15.135
直線距離にはなりません。

5
00:00:15.135 --> 00:00:21.188
例えば横に三、縦に四離れた二点の直線距離は、斜めの辺の長さである五です。

6
00:00:21.188 --> 00:00:25.224
この計算は、学校で習う三平方の定理そのものです。

7
00:00:25.224 --> 00:00:31.951
マス・ハイポットは、渡された数値をそれぞれ二乗して合計し、その平方根を返します。

8
00:00:31.951 --> 00:00:38.005
二点の座標の差を渡せば距離になり、ベクトルの成分を渡せば長さになります。

9
00:00:38.005 --> 00:00:44.731
ドラッグの移動量、円形の範囲判定、ゲームの接近判定など、身近な場面で活躍します。

10
00:00:44.731 --> 00:00:49.356
自力で二乗と平方根を書く方法と結果は同じですが、この後の章で見るように、

11
00:00:49.356 --> 00:00:53.980
大きな値への強さという違いもあります。

12
00:00:53.980 --> 00:00:55.417
まず動作環境です。

13
00:00:55.417 --> 00:01:00.845
この機能は、二千十五年七月以降、主要ブラウザーで広く使える機能です。

14
00:01:00.845 --> 00:01:07.870
現在のクローム、エッジ、ファイアフォックス、サファリなら、追加のライブラリーは不要です。

15
00:01:07.870 --> 00:01:12.580
画面要素に依存しない計算だけの処理なので、ブラウザー専用の仕組みを使わず、

16
00:01:12.580 --> 00:01:17.290
ノード・ジェイエスでも同じコードが動きます。

17
00:01:17.290 --> 00:01:23.437
記事のサンプルはノード・ジェイエス二十二系以降を対象にしていますが、これは記事が採用した条件で、

18
00:01:23.437 --> 00:01:29.584
この機能が二十二系で初めて入ったという意味ではありません。

19
00:01:29.584 --> 00:01:37.088
古いブラウザーや組み込み環境では、呼び出す前に存在を確認し、なければ処理を止めるのが安全です。

20
00:01:37.088 --> 00:01:39.367
基本の書き方を見ましょう。

21
00:01:39.367 --> 00:01:46.378
マス・ハイポットに、横方向の差ディーエックスと、縦方向の差ディーワイを渡します。

22
00:01:46.378 --> 00:01:51.198
変数名に座標の意味を持たせていますが、この仕組み自体に座標の概念はなく、

23
00:01:51.198 --> 00:01:56.018
どの値を渡すかは呼び出す側が決めます。

24
00:01:56.018 --> 00:01:58.122
ここで一番の注意点です。

25
00:01:58.122 --> 00:02:04.081
二点の距離がほしいときは、座標そのものではなく、差を渡してください。

26
00:02:04.081 --> 00:02:10.917
点エーが十と二十、点ビーが十三と二十四なら、差は三と四で、答えは五になります。

27
00:02:10.917 --> 00:02:19.156
もし十三と二十四をそのまま渡すと、原点から点ビーまでの距離という、別の計算になってしまいます。

28
00:02:19.156 --> 00:02:26.868
どちらの点から測りたいのかを意識して、必ず始点を引いてから渡すクセを付けておきましょう。

29
00:02:26.868 --> 00:02:29.311
引数と戻り値の規則を押さえます。

30
00:02:29.311 --> 00:02:33.052
引数の個数は決まっておらず、二次元なら二個、三次元なら三個というように、

31
00:02:33.052 --> 00:02:36.793
必要な成分だけを渡せます。

32
00:02:36.793 --> 00:02:41.221
戻り値は数値で、有限の数を渡した場合はゼロ以上になります。

33
00:02:41.221 --> 00:02:45.802
引数が空ならゼロが返り、一個だけ渡すとその絶対値が返ります。

34
00:02:45.802 --> 00:02:49.466
先ほどの三次元の例は、二と三と六で、二乗の合計が四と九と三十六で四十九になるため、

35
00:02:49.466 --> 00:02:53.131
答えは七です。

36
00:02:53.131 --> 00:02:56.337
この処理は同期的で、プロミスは返しません。

37
00:02:56.337 --> 00:02:59.086
アウェイトやコールバックは不要です。

38
00:02:59.086 --> 00:03:04.888
またマスから直接呼ぶ仕組みなので、ニュー・マスで何かを作る必要もありません。

39
00:03:04.888 --> 00:03:08.756
ここからは、入力検証まで含めた完全な例を組み立てます。

40
00:03:08.756 --> 00:03:14.488
まずマス・ハイポットが存在するかを確認し、対応していない環境ではそこで止めます。

41
00:03:14.488 --> 00:03:20.648
次に、始点と終点の四つの座標を受け取る、ディスタンス・ツーディーという関数を作ります。

42
00:03:20.648 --> 00:03:24.517
座標の検証にはナンバー・イズ・ファイナイトを使います。

43
00:03:24.517 --> 00:03:28.385
これは文字列を数値へ変換しない判定なので、文字列の三やヌル、ナンや無限大を、

44
00:03:28.385 --> 00:03:32.254
座標としてしっかり拒否できます。

45
00:03:32.254 --> 00:03:35.979
検証を通ったら座標の差をマス・ハイポットへ渡します。

46
00:03:35.979 --> 00:03:42.140
最後に計算結果が有限かどうかも確認し、範囲を超えていればレンジエラーを投げる設計です。

47
00:03:42.140 --> 00:03:45.041
作った関数を実行した結果を読みます。

48
00:03:45.041 --> 00:03:50.520
十と二十から十三と二十四までの距離は、差の三と四から五になりました。

49
00:03:50.520 --> 00:03:55.998
半径六と比較すると、五以下六なので、範囲内を表すトゥルーが返ります。

50
00:03:55.998 --> 00:03:59.060
始点と終点が同じ点なら距離はゼロです。

51
00:03:59.060 --> 00:04:00.994
三次元の長さは七でした。

52
00:04:00.994 --> 00:04:06.634
最後に、意図的に文字列の三を渡すと、検証でタイプエラーが投げられます。

53
00:04:06.634 --> 00:04:13.886
これをトライ・キャッチで受け取ることで、処理全体を止めずにエラーの内容だけを表示できます。

54
00:04:13.886 --> 00:04:20.009
ここまでの出力は、ノード・ジェイエスの実機でも同じになることを確認済みです。

55
00:04:20.009 --> 00:04:25.488
記事の元のサンプルも同じ結果で、計算の流れはこの例と共通しています。

56
00:04:25.488 --> 00:04:27.527
失敗しやすい落とし穴です。

57
00:04:27.527 --> 00:04:32.704
マス・ハイポット自体は、渡された値を数値へ変換してから計算します。

58
00:04:32.704 --> 00:04:37.567
そのため文字列の三を渡しても例外にはならず、五が返ってきます。

59
00:04:37.567 --> 00:04:41.332
数値に直せない文字列なら、結果はナンになります。

60
00:04:41.332 --> 00:04:46.352
つまり入力が間違っていても、必ずエラーになるとは限らないのです。

61
00:04:46.352 --> 00:04:54.667
フォームの入力を扱う場合は、空欄を許すのか、数値の文字列を受け付けるのかを先に決めてから変換してください。

62
00:04:54.667 --> 00:04:58.824
先ほどのサンプルが、変換済みの有限な数値だけを受け付ける設計にしたのは、

63
00:04:58.824 --> 00:05:02.981
この暗黙の変換に頼らないためです。

64
00:05:02.981 --> 00:05:07.060
検証の責任は、呼び出す側にあると覚えておきましょう。

65
00:05:07.060 --> 00:05:09.320
特殊な値の扱いも確認します。

66
00:05:09.320 --> 00:05:14.162
数値へ変換した結果がナンになると、基本的には結果もナンです。

67
00:05:14.162 --> 00:05:20.941
ただし例外があり、引数に正か負の無限大が一つでも含まれると、結果は無限大になります。

68
00:05:20.941 --> 00:05:26.752
実際にナンと無限大を一緒に渡すと、返ってくるのはナンではなく無限大です。

69
00:05:26.752 --> 00:05:33.370
ナンが含まれていれば必ずナンになる、と思い込んでいると、このケースを見落とします。

70
00:05:33.370 --> 00:05:38.131
実務では、入力の段階で有限かどうかを検証しておけば、こうした特殊な値の組み合わせを、

71
00:05:38.131 --> 00:05:42.893
計算の後で悩む必要はなくなります。

72
00:05:42.893 --> 00:05:46.928
境界のケースほど、検証を前倒しする価値があります。

73
00:05:46.928 --> 00:05:52.988
マス・ハイポットを使う大きな理由が、数値の桁あふれへの強さです。

74
00:05:52.988 --> 00:05:59.617
自力で二乗して平方根を求める書き方だと、最終的な答えは表現できる範囲内でも、

75
00:05:59.617 --> 00:06:06.245
途中の二乗が大きくなりすぎて無限大になってしまうことがあります。

76
00:06:06.245 --> 00:06:13.821
例えば一の後にゼロが二百個続くような大きな数では、その二乗自体が範囲を超えます。

77
00:06:13.821 --> 00:06:23.480
しかしマス・ハイポットに同じ数を二つ渡すと、約一・四一四二かける十の二百乗という正しい答えが返ります。

78
00:06:23.480 --> 00:06:29.540
逆に極端に小さい値の二乗がゼロになってしまう問題も避けられます。

79
00:06:29.540 --> 00:06:38.820
ただし、座標の差を求める引き算自体が先にあふれた場合は救えないので、結果の検証は引き続き大切です。

80
00:06:38.820 --> 00:06:40.629
活用場面を見ましょう。

81
00:06:40.629 --> 00:06:45.561
円形の操作範囲では、中心から対象までの距離と半径を比べます。

82
00:06:45.561 --> 00:06:51.644
以下、と書けば円周上の点も範囲内になり、未満に変えれば円周を除外できます。

83
00:06:51.644 --> 00:07:01.509
ドラッグ操作では、開始位置から現在位置までの距離を調べ、一定の距離を超えた時点でドラッグ開始と判断する使い方ができます。

84
00:07:01.509 --> 00:07:05.949
その際、両方の座標を同じ基準にそろえることが大切です。

85
00:07:05.949 --> 00:07:11.867
画面基準とページ基準を混ぜると、計算はできても意味の違う距離になります。

86
00:07:11.867 --> 00:07:17.786
なお、緯度と経度をそのまま渡して地球上の距離を求める用途には適しません。

87
00:07:17.786 --> 00:07:21.568
座標系と単位に合った計算方法を選んでください。

88
00:07:21.568 --> 00:07:23.117
制約とまとめです。

89
00:07:23.117 --> 00:07:32.066
マス・ハイポットは大きな値や小さな値に強い計算ですが、浮動小数点の丸め誤差まで消えるわけではありません。

90
00:07:32.066 --> 00:07:38.951
ちょうど境界線上かどうかを判定する場面では、用途に応じた許容差を設けてください。

91
00:07:38.951 --> 00:07:44.802
また実務で使うなら、まず入力の単位と許容範囲を決めることが近道です。

92
00:07:44.802 --> 00:07:50.568
画面のピクセルでも、ゲーム内の座標でも、計測値でも、呼び出す側で単位と座標系をそろえておけば、

93
00:07:50.568 --> 00:07:56.333
短い距離計算の関数を安全に使い回せます。

94
00:07:56.333 --> 00:08:01.152
二点の距離に迷ったら、差を取ってマス・ハイポットへ渡す。

95
00:08:01.152 --> 00:08:05.283
この流れを、検証とセットでぜひ活用してください。

96
00:08:05.283 --> 00:08:12.511
まずはコンソールで三と四を渡して五が返ることを確かめるところから始めてみてください。

97
00:08:12.511 --> 00:08:14.060
お疲れさまでした。
