Vue.jsでGeocoder APIを使ってみた (vue2-geocoder)

# はじめに
Vue.jsでGeocoder APIを呼び出し緯度/経度を取得してみた。

## Geocoder APIとは
住所を地理座標（緯度/経度）に変換できるAPIです。
参照 : https://developers.google.com/maps/documentation/geocoding/overview

## 使用ライブラリと詳細
* 使用ライブラリ : @pderas/vue2-geocoder
使用理由 : vue2のgeocoding用プラグインでよく使われている。
参照 : https://github.com/PDERAS/vue2-geocoder#readme

* query時に設定できるパラメータの説明
**(address_line_1)** : 住所での検索時使用するパラメータ
**(address_line_2)** : こちらも住所での検索時使用するパラメータですが、(address_line_1)だけで検索できます。
**(city)** : 都市の名前などで検索したいときのパラメータ
**(state)**: 国をアメリカなどの州を持つ国にした場合の、州検索時に使用するパラメータ
**(zip_code)** : 郵便番号で検索したいときのパラメータ  
**(country)** : 検索対象になる国の名前を絞り込むためのパラメータ[今回は日本に限定]上記パラメータを利用し、入力した際に緯度/経度を絞り込みます。

## Geocoder API Request / Response

```handleSetCity.ts

  private async handleSetCity() {
    let lat = 0
    let lon = 0

    const addressObj = {
      address_line_1: '東京都庁',
      address_line_2: '',
      city: '',
      state: '',
      zip_code:'',
      country: '日本'
    }

    (Vue as any).$geocoder.send(addressObj, (response: any) => {
      if (response.results) {
        lat = response.results[0].geometry.location.lat
        lon = response.results[0].geometry.location.lng
      }
    })
  }
```


* Response

```
[
    {
        "address_components": [
            {
                "long_name": "45階",
                "short_name": "45階",
                "types": [
                    "subpremise"
                ]
            },
            {
                "long_name": "第一本庁舎",
                "short_name": "第一本庁舎",
                "types": [
                    "establishment",
                    "point_of_interest"
                ]
            },
            {
                "long_name": "東京都庁",
                "short_name": "東京都庁",
                "types": [
                    "premise"
                ]
            },
            {
                "long_name": "１",
                "short_name": "１",
                "types": [
                    "premise"
                ]
            },
            {
                "long_name": "８",
                "short_name": "８",
                "types": [
                    "political",
                    "sublocality",
                    "sublocality_level_4"
                ]
            },
            {
                "long_name": "２丁目",
                "short_name": "２丁目",
                "types": [
                    "political",
                    "sublocality",
                    "sublocality_level_3"
                ]
            },
            {
                "long_name": "西新宿",
                "short_name": "西新宿",
                "types": [
                    "political",
                    "sublocality",
                    "sublocality_level_2"
                ]
            },
            {
                "long_name": "新宿区",
                "short_name": "新宿区",
                "types": [
                    "locality",
                    "political"
                ]
            },
            {
                "long_name": "東京都",
                "short_name": "東京都",
                "types": [
                    "administrative_area_level_1",
                    "political"
                ]
            },
            {
                "long_name": "日本",
                "short_name": "JP",
                "types": [
                    "country",
                    "political"
                ]
            },
            {
                "long_name": "163-8001",
                "short_name": "163-8001",
                "types": [
                    "postal_code"
                ]
            }
        ],
        "formatted_address": "日本、〒163-8001 東京都新宿区西新宿２丁目８−１ 東京都庁 45階 第一本庁舎",
        "geometry": {
            "location": {
                "lat": 35.6898531,
                "lng": 139.6917321
            },
            "location_type": "ROOFTOP",
            "viewport": {
                "northeast": {
                    "lat": 35.6912020802915,
                    "lng": 139.6930810802915
                },
                "southwest": {
                    "lat": 35.6885041197085,
                    "lng": 139.6903831197085
                }
            }
        },
        "place_id": "ChIJnctryNSMGGARLv4MknPFseU",
        "plus_code": {
            "compound_code": "MMQR+WM 日本、東京都新宿区",
            "global_code": "8Q7XMMQR+WM"
        },
        "types": [
            "establishment",
            "point_of_interest",
            "tourist_attraction"
        ]
    }
]
```

ただ、実際に緯度/経度を取得する場合に使用するのは、Responseのgeometry.locationの中身になります。

```
"geometry": {
  "location": {
    "lat": 35.6898531,
    "lng": 139.6917321
  },
・
・
・

```

## Geocoder APIのエラーハンドリング
Geocoder APIを使用した時のエラーハンドリングには、Geocoder APIに標準で返ってくる[エラーメッセージ]を使用すると良さげです。

* statusがOK以外のステータスコードを返す場合、Geocodingレスポンスオブジェクト内にerror_messageフィールドがある可能性があります。
このフィールドには、特定のステータスコードの背後にある理由に関する詳細情報が含まれています。  
参照 : https://developers.google.com/maps/documentation/geocoding/overview#StatusCodes

## vue2-geocoderを使用した時のエラー検証結果

* 検索が引っかからない場合
response : {"results":[],"status":"ZERO_RESULTS"}

* API_KEYを無効にした場合
response : {"error_message":"This API project is not authorized to use this API.","results":[],"status":"REQUEST_DENIED"}

## Geocoder APIの回数制限

GCP上でAPIごとに(Geocodingのみを)回数制限を設定することできます。
![スクリーンショット 2020-09-28 12.58.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/c922800b-cc6b-334e-c724-7c0ac3ce99e0.png)