Gelocationのデモアプリ

# はじめに
位置情報を用いたアプリケーションを作りたいと考えています。
アプリケーションは、ブラウザ、iOS、Androidを想定しています。
まずブラウザに着手しました。ブラウザならクロスプラットフォームですしね。
ブラウザの位置情報の機能は、JavaScriptのGeolocationが標準かと思います。
機能の調査を行い、デモアプリを作成しました。

<img width="320" alt="IMG_0049.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/68632/04f14e9d-9519-fe86-e567-0653076fad07.png">

# 概要

- Geolocationの紹介
- index.html
- index.js
- GitHub

# 詳細
## Geolocationの紹介
以下の機能があります。

- getCurrentPosition
    - 現在地を1回取得します。
- watchPosition
    - 現在地を複数回取得します。
- clearWatch
    - watchPositionの更新を停止します。

取得する現在地の情報の一覧です。

- latitude
    - 緯度
- longitude
    - 経度
- altitude
    - 高度(メートル)
- accuracy
    - latitude と longitude の精度(メートル)
- altitudeAccuracy
    - altitude の精度(メートル)
- heading
    - デバイスの移動方向
        - 真北 0
        - 東 90
        - 西 270
- speed
    - デバイスの移動速度(メートル/秒)

詳細は、下記のドキュメントが参考になると思います。
W3C [https://www.w3.org/TR/geolocation-API/](https://www.w3.org/TR/geolocation-API/)
MDN [https://developer.mozilla.org/en-US/docs/Web/API/Geolocation](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation)

## index.html

デモアプリでは、jQuery、Bootstrap、Animate CSSを使っています。解説は行いません。

ボタンを3つ作成し、それぞれ上記の機能の起動に対応させました。

```
<button type="button" class="btn btn-outline-primary" id="current">Current</button>
<button type="button" class="btn btn-outline-primary" id="watch">Watch</button>
<button type="button" class="btn btn-outline-primary" id="clear">Clear</button>
```

機能が実行されると現在地の情報で画面を更新します。

```
<div>latitude: <span class="latitude"></span></div>
<div>longitude: <span class="longitude"></span></div>
<div>altitude: <span class="altitude"></span></div>
<div>accuracy: <span class="accuracy"></span></div>
<div>altitudeAccuracy: <span class="altitudeAccuracy"></span></div>
<div>heading: <span class="heading"></span></div>
<div>speed: <span class="speed"></span></div>
<div>timestamp: <span class="timestamp"></span></div>
```

また、関連するメッセージを下部に表示します。

```
<div>message: <span class="message"></span></div>
```

## index.js

共通のオプションの値です。
enableHighAccuracyは、高精度を指定できます。
ただし、消費電力が増えたり、時間がかかったりします。この辺りは、トレードオフですね。
デフォルトは、falseです。
timeoutは、デフォルトは、無期限です。
maximumAgeは、位置情報のキャッシュ情報の期限です。0だと、キャッシュを利用しません。

```
var options = {
    enableHighAccuracy: true,
    timeout: 10000, // milliseconds
    maximumAge: 0 // 0 = the device cannot use a cached position
};
```

ブラウザがGeolocationを使えるか確認しています。
最近のブラウザはほぼ対応しているので、念の為のおまじないです。
確認後、画面の下部にメッセージを表示しています。
また、clear()は後半で説明します。

```
function geolocation() {
    clear();
    if (navigator.geolocation) {
        $('.message').html('Geolocation is available').animateCss('flash');
        return true
    } else {
        $('.message').html('Geolocation IS NOT available').animateCss('flash');
        return false
    }
}
```

getCurrentPositionです。画面のCurrentボタンをクリックすると起動します。
まず、上記のgeolocation()でブラウザが対応しているかチェックしています。
現在地の取得を実施し、成功したらsuccess()、失敗したらerror()を実行しています。
また、optionsは、上記で説明した通りです。

```
$('#current').on('click', function () {
    if (!geolocation()) {
        return
    }
    navigator.geolocation.getCurrentPosition(
        function (pos) {success(pos, 'current')},
        function (err) {error(err)},
        options
    );
});
```

watchPositionです。画面のWatchボタンをクリックすると起動します。
getCurrentPositionとほぼ一緒ですが、実行後の返却値をwatchIdに保存しています。
clearWatch()は、このwatchIdを利用して現在地の取得を中止します。

```
var watchId = null;
$('#watch').on('click', function () {
    if (!geolocation()) {
        return
    }
    watchId = navigator.geolocation.watchPosition(
        function (pos) {success(pos, 'watch')},
        function (err) {error(err)},
        options
    );
});
```

getCurrentPositionとwatchPositionを実行し、成功した場合に実行されます。
画面の情報を更新する部分です。
watchPositionの場合は、位置情報が更新されるたびに実行されます。

```
function success(pos, method) {
    $('.latitude').html(pos.coords.latitude);
    $('.longitude').html(pos.coords.longitude);
    $('.altitude').html(pos.coords.altitude);
    $('.accuracy').html(pos.coords.accuracy);
    $('.altitudeAccuracy').html(pos.coords.altitudeAccuracy);
    $('.heading').html(pos.coords.heading);
    $('.speed').html(pos.coords.speed);
    $('.timestamp').html(pos.timestamp);
    switch(method)
    {
        case 'current':
        $('.message').html('Current OK').animateCss('flash');
        break;
        case 'watch':
        $('.message').html('Watch OK').animateCss('flash');
        break;
    }
}
```

getCurrentPositionとwatchPositionを実行し、失敗した場合に実行されます。
エラーコードは、1、2、3が存在します。
1は、PERMISSION_DENIEDが定義されていて、主に、SSL環境出ない場合に表示されるようです。
2は、POSITION_UNAVAILABLEが定義されていて、何らかの内部エラーの場合に表示されるようです。
3は、optionsのtimeoutで指定を超過した場合に表示されるようです。
1、2、3以外は返却されないようですが、デバッグ用にerr.messageと言う値があります。通常は利用しないはずですが、一応表示するようにしてみました。

```
function error(err) {
    switch(err.code)
    {
        case 1:
        $('.message').html('PERMISSION_DENIED').animateCss('flash');
        break;
        case 2:
        $('.message').html('POSITION_UNAVAILABLE').animateCss('flash');
        break;
        case 3:
        $('.message').html('TIMEOUT').animateCss('flash');
        break;
        $('.message').html(err.message).animateCss('flash');
        break;
    }
}
```

clearWatchです。画面のClearボタンをクリックすると起動します。
画面と各種変数の初期化を行なっています。

```
$('#clear').on('click', function () {
    clear();
    $('.message').html('Clear OK').animateCss('flash');
});
```


上記で度々clear()がありましたが、ここでは、画面の初期化とwatchPositionの初期化をwatchIdを利用しておこなっています。

```
function clear() {
    $('.latitude').html('');
    $('.longitude').html('');
    $('.altitude').html('');
    $('.accuracy').html('');
    $('.altitudeAccuracy').html('');
    $('.heading').html('');
    $('.speed').html('');
    $('.timestamp').html('');
    if (watchId) {
        navigator.geolocation.clearWatch(watchId);
        watchId = null;
    }
}
```

## GitHub
上記のソースコードの完全版は下記にありますので、参考にしてください。
[https://github.com/maedamikio/public/tree/master/geolocation](https://github.com/maedamikio/public/tree/master/geolocation)

# おわりに
Geolocationの基本的な使い方が理解出来ました。
この知見をベースにアプリケーションの作成へ進みたいと思います。

実は、初めてJavaScriptを使ってみました。正確に言うと、今までもコピペで何となく利用していましたが、理解しながら使ったのは初めてです。
jQuery、Bootstrap、Animate CSSも使うことになり、良い勉強になりました。