Edited at

ブラウザで現在地を取得し、目的地までの距離を算出する

More than 1 year has passed since last update.

html5-geolocation-api.png

・ブラウザから現在地の座標を取得

・「現在地から検索」を可能にするために、座標データをクエリパラメータとして受け取れるようにする。

・受け取った座標データを元に、目的地(の座標)までの距離を算出する。

備忘録として簡潔にまとめておきたいと思います。


Geolocation APIで現在地の座標を取得

まずはブラウザ経由で現在地の座標データを取得します。Geolocation APIという便利なAPIがあるので、それを使っています。

//関数を定義

function geoFindUser() {
//ユーザーのブラウザがGeolocation APIに対応していた場合
if (navigator.geolocation) {

//getCurrentPositionメソッドで現在地を取得
navigator.geolocation.getCurrentPosition(

//現在地の取得に成功した場合の処理
function(position) {

//データを変数にして整理(position.coords.latitude/longitudeが座標)
var lat = position.coords.latitude;
var lng = position.coords.longitude;

//座標のデータをクエリパラメータとし、座標データを渡したいページに遷移させる
//Javascriptで文字列の中に変数を入れたいときは、バッククオートで囲む
window.location.href = `/"something"/searches?latitude=${lat}&longitude=${lng}`
},

//現在地の取得に失敗した場合の処理
function (error) {
//エラー情報を配列として定義
var errorInfo = [
"原因不明のエラーが発生しました…。" ,
"位置情報の取得が許可されませんでした…。" ,
"電波状況などで位置情報が取得できませんでした…。" ,
"位置情報の取得に時間がかかり過ぎてタイムアウトしました…。"
] ;

//エラーコードを変数に代入(エラーコードはgetCurrentPositionの引数として受け取っている)
var errorNo = error.code ;
//エラーメッセージに、先に定義したエラーコードと、エラー番号に対応した情報をalert表示させる
var errorMessage = "[エラー番号: " + errorNo + "]\n" + errorInfo[ errorNo ] ;
alert( errorMessage ) ;
}
//オプション設定(10秒でタイムアウトになる)
{
"enableHighAccuracy": false,
"timeout": 10000,
"maximumAge": 0,
}
);
}

//ユーザーのブラウザがGeolocation APIに対応していなかった場合の処理
else {
var errorMessage = "お使いの端末は、GeoLacation APIに対応していません。" ;

alert( errorMessage ) ;
}
}


座標間の距離を算出するメソッドを作成

次に、座標間の距離を算出するプログラムをつくります。※モジュールの特異メソッドとして定義することで、各クラスにミックスインことなくメソッドを呼び出せるようにしています。

module GetDistance

def self.distance(lat1, lng1, lat2, lng2)
# ラジアン単位に変換
x1 = lat1.to_f * Math::PI / 180
y1 = lng1.to_f * Math::PI / 180
x2 = lat2.to_f * Math::PI / 180
y2 = lng2.to_f * Math::PI / 180

# 地球の半径 (km)
radius = 6378.137

# 差の絶対値
diff_y = (y1 - y2).abs

calc1 = Math.cos(x2) * Math.sin(diff_y)
calc2 = Math.cos(x1) * Math.sin(x2) - Math.sin(x1) * Math.cos(x2) * Math.cos(diff_y)

# 分子
numerator = Math.sqrt(calc1 ** 2 + calc2 ** 2)

# 分母
denominator = Math.sin(x1) * Math.sin(x2) + Math.cos(x1) * Math.cos(x2) * Math.cos(diff_y)

# 弧度
degree = Math.atan2(numerator, denominator)

# 大円距離 (km)
degree * radius
end

end


現在地から目的地までの距離を算出

目的地は大阪駅を想定。

#受け取ったクエリパラメータ(座標データ)を変数に代入

lat1 = params[:latitude]
lng1 = params[:longitude]

#目的地の座標を変数に代入
#※geocoderというgemを利用すれば、DBの住所カラムから自動で座標を生成してくれたりする。ここでは省略
lat2 = 34.702485
lang2 = 135.495951
#上記の座標は大阪駅のもの

#先ほど定義したモジュールの特異メソッドに、座標データを引数として渡し、計算
GetDistance.distance(lat1, lng1, lat2, lng2).round(2)

#出力成功!
=>15.86


まとめ

シンプルだけど応用がききそう。geocoderでデータベースに座標データを生成したら、現在地から検索機能も簡単に実装できるね〜。


参考

Geolocation API

【Ruby on Rails】緯度経度から 2 点間の距離を算出する