位置情報をブラウザで取得するGeolocation APIを使って今いる住所を調べる

Javascript

Geolocation APIの位置情報を調べることがあったので、わかったことをメモしておこうと思います。

前提条件

  • 現在よく使われている新しいブラウザはhttpでは動かないことが多いようです。httpsなら使えるとのこと。
  • 緯度経度から住所を取得するのにはGoogle Maps APIなど外部APIを使うことが必要。使わない場合は経度緯度情報など自分で用意する必要がある。
  • 現在地からそこそこずれる(こともある)

Geolocation API

ブラウザがGeolocation APIを使えるか調べる

まずは使用しているブラウザがGeolocation APIを使えるかどうか調べるにはこうします。

if( navigator.geolocation ){
	// 現在位置を取得できる場合の処理
} else {
	// 現在位置を取得できない場合の処理
}

現在の位置を取得

ブラウザでAPIが使える場合、次に位置を取得します。

navigator.geolocation.getCurrentPosition( success, error, option);
  • success 位置が取得できた場合に行う処理
  • error 位置が取得できなかった場合に行う処理
  • option オプションの指定

位置が取得できた場合に行う処理

位置が取得できた場合に行う処理では以下の値が取得できます。

  • coords.latitude 現在位置の緯度
  • coords.longitude 現在位置の経度。
  • coords.altitude 現在位置の高度。メートル単位。
  • coords.accuracy 取得した緯度、経度の精度。メートル単位。
  • coords.altitudeAccuracy 取得した高度の精度。メートル単位。
  • coords.heading 方角。0〜360の角度で表す。0が北、90が東、180が南、270が西。
  • coords.speed 速度。メートル/秒数。位置情報を追跡する場合に使用。

今回必要なのは緯度・経度の2つです。

位置が取得できなかった場合に行う処理

位置が取得できなかった場合はエラーの数字が渡され以下の内容になります。

  • 0 原因不明。
  • 1 ユーザーが、位置情報の使用を許可しない。
  • 2 何らかの理由で、位置を取得できない。
  • 3 タイムアウト。

オプション

オプションは以下の3つです

  • enableHighAccuracy true/falseを指定。精度の高い情報を取得する。
  • timeout 秒数をミリ単位で指定。タイムアウトするまでの時間。
  • maximumAge 秒数をミリ単位で指定。キャッシュの有効期限。

watchPosition()という追跡機能もあるようですが、今回は使わないため省略。

Google Maps API

上記のGeolocation APIから取得できた緯度経度で住所を調べたいのですが、それには緯度経度情報が必要で自分で用意するのは大変そうなので、既存の地図サービスのAPI( 今回はGoogle Maps)を使います。APIキーを取得しないといけないので、以下のページにしたがったAPIキーを取得し、jsを読み込みます。

<script src="https://maps.googleapis.com/maps/api/js?key=APIキー"></script>

Geolocation APIとGoogle Maps APIを合わせて住所を取得

2つのAPIを合わせて住所を取得するのは以下のコードになります。

<script>
if( navigator.geolocation ){// 現在位置を取得できる場合の処理

	// 現在位置を取得する
	navigator.geolocation.getCurrentPosition( success, error, option);
	
	/*現在位置が取得できた時に実行*/
	function success(position){
		var data = position.coords;

		// 必要な緯度経度だけ取得
		var lat = data.latitude;
		var lng = data.longitude;

		//Google Mapsで住所を取得
		var geocoder = new google.maps.Geocoder();
        latlng = new google.maps.LatLng(lat, lng);
        geocoder.geocode({'latLng': latlng}, function(results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                document.getElementById('address').innerHTML = results[0].formatted_address;
            }
            else {
                alert("エラー" + status);
            }
        });
	}

	/*現在位置の取得に失敗した時に実行*/
	function error(error){
		var errorMessage = {
			0: "原因不明のエラーが発生しました。",
			1: "位置情報が許可されませんでした。",
			2: "位置情報が取得できませんでした。",
			3: "タイムアウトしました。",
		} ;
		//とりあえずalert
		alert( errorMessage[error.code]);
	}

	// オプション(省略可)
	var option = {
		"enableHighAccuracy": false,
		"timeout": 100 ,
		"maximumAge": 100 ,
	} ;

} else {// 現在位置を取得できない場合の処理
	//とりあえずalert
	alert("あなたの端末では、現在位置を取得できません。");
}

</script>
<div id="address"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=APIキー"></script>

取得ができていれば、「日本、〒000-0000 ○○都○○区○○1丁目11−1」のように表示されます。

先程の住所に地図をつける

参考サイトのコードでは元々地図が表示されるのを使用しないため消していただけなので、取得した位置情報の地図を出すのも続けてできます。

<script>
if( navigator.geolocation ){ // 現在位置を取得できる場合の処理

	// 現在位置を取得する
	navigator.geolocation.getCurrentPosition( success, error, option);
	
	/*現在位置が取得できた時に実行*/
	function success(position){
		var data = position.coords ;

		// 必要な緯度経度だけ取得
		var lat = data.latitude;
		var lng = data.longitude;

		//Google Maps
		var geocoder = new google.maps.Geocoder();
        latlng = new google.maps.LatLng(lat, lng);
        geocoder.geocode({'latLng': latlng}, function(results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                map.setCenter(latlng);
                var marker = new google.maps.Marker({
                    map: map,
                    position: latlng
                });
                google.maps.event.addListener(marker, 'click', function (e) {
                    infowindow.setContent(results[0].formatted_address);
                    infowindow.open(map, marker);
                });
                document.getElementById('address').innerHTML = results[0].formatted_address;
            }
            else {
                alert("エラー" + status);
            }
        });
	}

	/*現在位置の取得に失敗した時に実行する関数名*/
	function error(error){
		var errorMessage = {
			0: "原因不明のエラーが発生しました。",
			1: "位置情報が許可されませんでした。",
			2: "位置情報が取得できませんでした。",
			3: "タイムアウトしました。",
		} ;
		//とりあえずalert
		alert( errorMessage[error.code]);
	}

	// オプション(省略可)
	var option = {
		"enableHighAccuracy": false,
		"timeout": 100 ,
		"maximumAge": 100 ,
	};

//MAPの表示
var map;
function initMap() {
    map = new google.maps.Map(document.getElementById('sample'), {
        zoom: 15
    });
}

} else {// 現在位置を取得できない場合の処理
	//とりあえずalert
	alert("あなたの端末では、現在位置を取得できません。");
}

</script>
<div id="sample" style="width: 700px; height: 400px;"></div>
<div id="address"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=APIキー&callback=initMap"></script>

こちらも取得ができていれば地図が表示され、「日本、〒000-0000 ○○都○○区○○1丁目11−1」のように住所が表示されます。

その他・県庁所在地に近い順にソートする

調べているときに見つけたのですが、Geolocation APIを使って現在地から県庁所在地の近い順に都道府県をソートするというものもありました。 こちらは県庁所在地の位置を自分で持つためGoogle Maps APIは不要です。