Geolocation API

位置情報を連続して取得する

 現在位置を取得する方法として getCurrentPosition()メソッドを紹介しましたが、これは一度だけ位置情報を取得するだけです。しかし、連続して位置情報を取得するための watchPosition()メソッドも用意されています。

連続して位置情報を取得する


var watchId = navigator.geolocation.watchPosition(
	successCallback,
	errorCallback,
	options
);

 基本的な使い方は、getCurrentPosition()と同じです。使い方の詳細は、「 現在位置を取得する 」で確認してください。

 この watchPosition()メソッドが呼び出されると、非同期に位置情報取得処理が繰り返し行われ、常に位置情報を監視した状態になります。このメソッドが呼び出されるとすぐに、その監視識別 ID を返します。これは、clearWatch()メソッドの引数に使います。

 この watchPosition()メソッドも最大で 3つの引数を取ります。

第一引数 successCallback
これは、位置情報取得に成功した時に実行される関数のオブジェクトを指定します。位置情報が変わる度に何度もこの関数が呼び出されることになります。第一引数は必須です。
第二引数 errorCallback
これは、位置情報取得に失敗した時に実行される関数オブジェクトを指定します。
第三引数 options
これは、位置情報取得に関する各種パラメータを格納した JavaScriptオブジェクトを指定します。

watchPosition()のプロセスを停止するためのメソッド


navigator.geolocation.clearWatch(watchId);

 引数に指定した監視識別 ID に一致する watchPosition()のプロセスがあれば、それを停止します。

 watchPosition()メソッドは、clearWatch()メソッドで停止されるまで、位置情報をモニタリングし続けます。移動を検知する度に、watchPosition()メソッドの第一引数に指定した関数が呼び出されることになります。watchPosition()メソッドに指定する引数は、getCurrentPosition()メソッドと同じです。

 watchPositon()メソッドは、移動しながら位置情報を取得すると、GPS高度や移動速度や移動方向を取得することができます。

 次のサンプルは、watchPositon()メソッドを使って位置情報をリアルタイムに表示します。

>> サンプルの表示

HTML source


<dl>
	<dt>緯度</dt>
	<dd id="latitude">-</dd>

	<dt>経度</dt>
	<dd id="longitude">-</dd>

	<dt>緯度・経度の精度</dt>
	<dd id="accuracy">-</dd>

	<dt>GPS 高度</dt>
	<dd id="altitude">-</dd>

	<dt>GPS 高度の精度</dt>
	<dd id="altitudeAccuracy">-</dd>

	<dt>移動方向</dt>
	<dd id="heading">-</dd>

	<dt>移動速度</dt>
	<dd id="speed">-</dd>

	<dt>タイムスタンプ</dt>
	<dd id="timestamp">-</dd>
</dl>

>> サンプルの表示

JavaScript source


document.addEventListener("DOMContentLoaded", function() {
	// オプション・パラメータをセット
	var position_options = {
		// 高精度を要求する
		enableHighAccuracy: true,
		// 最大待ち時間(ミリ秒)
		timeout: 60000,
		// キャッシュ有効期間(ミリ秒)
		maximumAge: 0
	};
	// 現在位置情報を取得
	navigator.geolocation.watchPosition(monitor, null, position_options);
}, false);

// 位置情報取得完了時の処理
function monitor(event) {
	// 緯度
	var latitude = event.coords.latitude;
	document.querySelector('#latitude').textContent = latitude;
	// 経度
	var longitude = event.coords.longitude;
	document.querySelector('#longitude').textContent = longitude;
	// 緯度・経度の精度
	var accuracy = event.coords.accuracy;
	document.querySelector('#accuracy').textContent = accuracy;
	// GPS 高度
	var altitude = event.coords.altitude;
	document.querySelector('#altitude').textContent = altitude;
	// GPS 高度の精度
	var altitudeAccuracy = event.coords.altitudeAccuracy;
	document.querySelector('#altitudeAccuracy').textContent = altitudeAccuracy;
	// 移動方向
	var heading = event.coords.heading;
	document.querySelector('#heading').textContent = heading;
	// 移動速度
	var speed = event.coords.speed;
	document.querySelector('#speed').textContent = speed;
	// タイムスタンプ
	var date = event.timestamp;
	if( typeof(date) == "number" ) {
		date = new Date(date);
	}
	document.querySelector('#timestamp').textContent = date.toString();
}

>> サンプルの表示

サンプルの結果

>> サンプルの表示

 この結果は、iPhoneを使って、実際に移動しながらリアルタイムに位置情報を取得した結果です。GPS高度、GPS高度の精度、移動方向、移動速度が取得できていることがわかります。本来は緯度と経度も同じように数字が動き続けるのですが、個人情報保護の観点から小数点第二位以下を切り捨てて表示しています。

 移動方向は、真北を 0°として全方向を時計回りに 360°で表した角度です。北が 0°、東が 90°、南が 180°、西が 270°ですから、この 210°〜240°ぐらいという結果は、概ね南西の方向に向かって移動していたことを表しています。

iPhone のコンパス

 移動速度は 1秒間に移動した距離をメートルで表したものですから、0.3m/sぐらいという結果は、

0.3m×3600秒(1時間)÷1000≒1km/h

で移動していたことを表します。

 watchPosition()メソッドでリアルタイム監視を行うと、ある程度の速度で移動中であれば 1秒くらいの間隔で、第一引数に指定したコールバック関数が呼び出されます。そして、移動をやめて停止すると、その呼び出しが止まります。再度、移動を開始すれば、自動的にコールバックの呼び出しが再開されることになります。

 上記のサンプルは、これまでのサンプルから getCurrentPosition()メソッドを watchPosition()メソッドに置き換えた点がポイントです。また、このサンプルではエラー・ハンドリングを行ないませんが、パラメータ・オプションを指定します。そのため、watchPosition()メソッドの第二引数にはコールバック関数のオブジェクトではなく null を指定してあります。

GPS高度

 GPS高度を表す altitudeプロパティの値には注意してください。上記のサンプルでは、GPS高度が 12.5mほどでした。しかし、この値は、標高でもなく、海抜でもなく、地上高(地面からの高さ)でもありません。この値は回転楕円体高度と呼ばれ、GPSが採用している世界測地系 WGS84の基準となる回転楕円体の表面からの高さを表しています。

 地球は完全な球ではなく、自転の影響を受けて赤道付近が膨らんだ回転楕円体になります。さらに、地表は平坦ではありません。山もあれば谷もあります。そのため、WGS84などの世界測地系では、地球を平らな回転楕円体と見なして位置や高さを測ります。つまり、実在しない計算上の地表を想定しているのです。

 この GPS高度は、実際の標高と比べると、東京付近であれば概ね 40mほど大きな値になります。つまり、GPS高度の基準となる計算上の地表とは、実際の地面よりかなり低い位置ということになります。この差は日本国内でも地域によって異なります。もし標高を正確に求めるとなると、簡単にはいきません。GPS高度と標高の関係は国土地理院のホームページで解説されていますので興味のある方はご覧になってください。

 このように、Geolocation APIが返す GPS高度は、私たちが直感的に理解している値とは異なりますので、その値そのものを使うことはできません。しかし、例えば、多地点で計測した GPS高度から、その差を評価することに意味はあるかもしれません。

リアルタイム監視の停止

 watchPosition()メソッドでリアルタイム監視を定義してしまうと、停止するまでリアルタイム監視が継続されてしまいます。GPSを搭載したスマート・フォンでは、バッテリーを無駄に消費してしまいますので注意が必要です。もしリアルタイム監視を行う場合には、監視が不要になったら clearWatch()メソッドでリアルタイム監視を停止した方が良いでしょう。

 次のサンプルは、開始ボタンを押すとリアルタイム監視を開始し、移動が行なわれれば、その方向をリアルタイムに表示します。もう一度ボタンを押すと、リアルタイム監視を停止します。

>> サンプルの表示

HTML source


<p><button type="button">開始</button></p>

<dl>
	<dt>緯度</dt>
	<dd id="latitude">-</dd>

	<dt>経度</dt>
	<dd id="longitude">-</dd>
</dl>

>> サンプルの表示

JavaScript source


document.addEventListener("DOMContentLoaded", function() {
	// 監視識別ID
	var watch_id = 0;
	// ボタンにclickイベントのリスナーをセット
	var button = document.querySelector('button');
	button.addEventListener("click", function() {
		if( watch_id > 0 ) {
			// リアルタイム監視を停止
			navigator.geolocation.clearWatch(watch_id);
			// 監視識別IDに0をセット
			watch_id = 0;
			// ボタン表記を変更
			button.textContent = " 開始 ";
		} else {
			// リアルタイム監視を開始
			watch_id = navigator.geolocation.watchPosition(monitor);
			// ボタン表記を変更
			button.textContent = " 停止 ";
		}
	}, false);
}, false);

// リアルタイム監視
function monitor(event) {
	// 緯度
	var latitude = event.coords.latitude;
	document.querySelector('#latitude').textContent = latitude;
	// 経度
	var longitude = event.coords.longitude;
	document.querySelector('#longitude').textContent = longitude;
}

>> サンプルの表示

サンプルの結果
サンプルのiPhone画像

>> サンプルの表示

 watchPosition()メソッドはリアルタイム監視のセットに成功すると、 0 より大きい数値を返します。そのため、このスクリプトでは、監視識別 ID を格納した変数 watch_id の値を評価することで、監視中なのか停止中なのかを判定しています。

 clearWatch()メソッドには、watchPosition()メソッドが返した監視識別 ID の値を第一引数に指定します。こうすることで、これまで継続してきたリアルタイム監視が停止します。