たまちゃんのブログ

日々学んだ技術を書き残してます。

Vue.js+Typescriptで住所からGoogle mapを表示する方法

js-api-loaderを使います。 www.npmjs.com

Vueの公式ドキュメントだと、google-maps-api-loaderが使われていますが、3年位更新されていません。 npmのページにいくと、js-api-loaderが推奨されています。

vuejs.org

Google map導入

まずは、完成形から。

[GoogleMap.vue]

<template>
  <div>
    <div id="map" style="width: 500px; height: 300px" />
  </div>
</template>

<script lang="ts">
import { Loader } from '@googlemaps/js-api-loader'

interface GoogleMap {
  google: any
  mapOptions: google.maps.MapOptions
}

export default Vue.extend({
  data(): GoogleMap {
    return {
      google: null,
      mapOptions: {
        center: {
          lat: 0,
          lng: 0
        },
        zoom: 15
      }
    }
  },
  async mounted(): Promise<void> {
    const googleMapApi = await new Loader({
      apiKey: process.env.GOOGLE_MAP_API_KEY ?? '',
      libraries: ['places']
    })
    await googleMapApi.load().then(() => {
      this.google = window.google
      this.initializeMap()
    })
  },
  methods: {
    initializeMap() {
      const map = new this.google.maps.Map(
        document.getElementById('map'),
        this.mapOptions
      )
      const geocoder = new this.google.maps.Geocoder()
      this.geocodeAddress(geocoder, map)
    },
    geocodeAddress(
      geocoder: google.maps.Geocoder,
      resultsMap: google.maps.Map
    ) {
      const address = '東京タワー'
      const vm = this
      geocoder.geocode(
        { address },
        (
          results: google.maps.GeocoderResult[] | null,
          status: google.maps.GeocoderStatus
        ) => {
          if (status === 'OK' && results) {
            if (results[0]) {
              resultsMap.setCenter(results[0].geometry.location)
              const marker = new this.google.maps.Marker({
                map: resultsMap,
                position: results[0].geometry.location
              })
              marker.setMap(resultsMap)
            }
          }
        }
      )
    }
  }
})
</script>

js-api-loader導入

ドキュメントにあるnew Loaderを、Vueの場合は、mounted()の中に入れて、マウント時に実行します。

ここはVue用に書き換える必要があるので、苦労しました。 ドキュメントは、Javascriptを使う時の書き方になっています。

定義ファイル導入

developers.google.com

npm i -D @types/google.maps コマンドで、定義ファイルをインストールします。

これも記述しておきましょう。

[tsconfig.json]

{
  "compilerOptions": {
    "types": ["google.maps"]
  }
}

定義ファイルを入れておかないと、google is not definedが出てしまいます。

型付け

 results: google.maps.GeocoderResult[] | null,
          status: google.maps.GeocoderStatus
geocoder: google.maps.Geocoder,
      resultsMap: google.maps.Map

あたりの型は、Google map APIのドキュメントから調べました。 調べるのめんどいですが、型付けは大事ですね。

コンポーネント呼び出し

index.vueとか、Google Mapを表示させたいところでコンポーネントを呼び出します。

<google-map />

<script>
import GoogleMap from '../GoogleMap.vue'
</script>

めっちゃ雑に書きました笑

コンポーネントを呼び出す際に、propsに住所やズーム度合いなどを渡してあげると、使いまわせそうです。

苦労したところ

typescriptの情報が少なかったですね。

vue.js google map apiとかで調べると、vue2-google-mapsが出てくるのですが、Githubのissueを見ると、Typescriptに対応していないらしいんですね。
定義ファイルを自作すればいけるっぽいんですが、ここでドハマリしました。。

わからなくなったら、公式ドキュメントを見るべしですね。
Qiitaとかの方がわかりやすいですが、情報が古かったり、環境が合っていなかったりするので。

この記事にも公式ドキュメントのリンクを貼っているので、ちゃんと確認してくださいね。