Vue.jsのアプリケーションの中でGoogle Mapを利用した場合にvue2-google-mapsといった既存のライブラリを使うことができます。本文書ではライブラリを利用することなくGoogleが提供しているscriptタグを利用してVue.jsでGoogle Mapを利用する方法を解説しています。

Vue CLIでVueプロジェクトを作成して動作確認を行なっています。Vueを起動するまでの詳しい説明は行っていません。

Google Mapsライブラリの利用はscriptタグを通して行います。scriptをどのように追加するかによって設定方法が変わります。本文書では、Google Mapsライブラリのscriptタグをindex.htmlに追加する方法とscriptタグをJavaScriptを利用して動的に追加する方法で動作確認を行っています。動作確認する中で発生した問題の対応方法についても記述しています。

最後にGoogleMapを利用したプラグインの作成方法についても学んでいきます。プラグインを作成する際には動的にscriptタグを追加する方法を利用します。全体を通してポイントとなるのがはwindowオブジェクトの利用、scriptタグの動的な追加、ライブラリのロード完了のタイミングです。GoogleMapに限定した話ではなく他でも利用できる知識だと思うのでこの機会にぜひ理解を深めてください。

Googleアカウントの作成

Google Mapを利用するためにはGoogleアカウントが必要となります。普段使っているアカウントを利用したくない人は新規で作成を行ってください。

Googleアカウントを取得するためには本人確認のために電話番号が必要となる場合があります。

Google Cloud Platformの登録

Googleアカウント取得後はGoogle Mapを利用するために必要となるAPIキーを取得するためにGoogle Maps Platformにアクセスします。Google Mapを利用は1 か月あたり 28,500 回(200ドル)まで無料の地図読み込みを行うことができます。

Google Mapようこそ画面
Google Mapようこそ画面

右上の”始める”ボタンをクリックするとGoogle Cloud Platformの無料トライアルの登録画面が表示されるので必要な情報を入力する必要があります。利用規約の確認と電話番号、個人情報、クレジットカード情報の入力が必要となります。

ステップ1/3でアカウント情報の確認が行われます。利用するGmailアカウント、国、組織またはニーズの説明を選択する必要があります。選択肢の中から当てはまるものを選択してください。ここでは個人的なプロジェクトを選択しています。

アカウント情報の確認画面
アカウント情報の確認画面

”続行”ボタンをクリックするとIDの確認と連絡先情報をいうことで連絡先である電話番号を入力する必要があります。入力すると電話に6桁のコードが送信されています。

電話番号の入力
電話番号の入力

受信したコードを次の画面で入力します。

6桁のコード入力画面
6桁のコード入力画面

支払い方法や住所の入力を求めらるので入力を行う必要があります。

クレジットカードなどの情報を入力
クレジットカードなどの情報を入力

上記のページの説明にある通りGoogle Platformの無料トライアルの登録なので90日間で300ドルのクレジットが無料で使えます。無料トライアル期間が終了しても自動的には請求されることはありません。

Google Maps Platformの有効化のためにいくつか質問があるので該当するものを選択して”送信”ボタンをクリックしてください。

Google Maps Platform有効化の前に質問
Google Maps Platform有効化の前に質問

後からでも確認できますがAPIキーが表示されているのでこのキーを利用することでGoogle Mapを利用することができます。

APIの表示
APIの表示

ようこそ画面が表示されます。これでGoogle Mapを利用するまでの設定は完了です。

ようこそ画面
ようこそ画面

利用する認証キーを確認したい場合は左側のメニューの認証情報をクリックしてください。

認証情報の確認
認証情報の確認

Vue.jsの環境構築

本書ではVue.jsはVue CLIを使って作成します。


 % vue create vue-google-map 

Default Vue 3を選択します。


? Please pick a preset: (Use arrow keys)
   Default ([Vue 2] babel, eslint) 
❯ Default (Vue 3 Preview) ([Vue 3] babel, eslint) 
  Manually select features 

インストールが完了したら、componentsフォルダにGoogleMap.vueファイルを作成します。

GoogleMap.vueファイルにはh1タグを記述します。


<template>
  <h1>Google Map</h1>
</template>

App.vueファイルを開いて、Hello Worldコンポーネントを作成したGoogleMapコンポーネントに変更します。


<template>
  <google-map />
</template>

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

export default {
  name: 'App',
  components: {
    GoogleMap
  }
}
</script>

プロジェクトフォルダでnpm run devコマンドを実行して下記の画面が表示されることを確認します。

Vue.jsの動作確認
Vue.jsの動作確認

Vue.jsの環境構築は完了です。

スクリプトタグを利用した表示方法

publicフォルダにあるindex.htmlにscriptタグを追加してGoogle Mapの表示を行います。Google Mapの公式ドキュメントを参考にしながら行っています。

ドキュメントに記載されているscriptタグは下記となります。本文書ではkeyの設定値にはYOUR_API_KEYと記述していますがここには各自がGoogle Maps Platformで取得したAPIキーを設定してください。利用する人によって設定する値は変わります。


<script async
    src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>

callback=initMapが設定されているためGoogle Mapのロードが完了するとinitMap関数が実行されますが定義していないためエラーが発生します。のちほどinitMap関数を利用しますがここでは削除しています。


<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
    <title><%= htmlWebpackPlugin.options.title %></title>
    <script
      async
      src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"
    ></script>
  </head>
  <body>
    <noscript>
      <strong
        >We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
        properly without JavaScript enabled. Please enable it to
        continue.</strong
      >
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

ブラウザで確認すると何も変化はありませんがデベロッパーツールのコンソールでgoogleと打つとscriptタグによって作成されたgoogleオブジェクトを確認することができます。index.htmlにscriptタグを追加することでGoogle Mapをが利用できることがわかります。

コンソールでgoogleを確認
コンソールでgoogleを確認

Vue.js内でのgoogleオブジェクトの確認

Vue.jsの中でGoogle Mapを扱うためライフサイクルフックmountedの中でgoogleオブジェクトを確認します。


<template>
  <h1>Google Map</h1>
</template>

<script>
export default {
  mounted(){
    console.log(window.google)
  }
}
</script>

デベロッパーツールで確認するとGoogle Mapのロードが完了していない時にはundefinedと表示され、ロードが完了している場合はmapsが表示されます。

ロードの完了を確認する処理を追加しておきます。後ほどエラーの内容を見せますがロードの完了ができていない場合にはGoogle Mapを利用することができません。

setIntervalを利用して500ms毎にwindow.googleの値をチェック(値があればロード完了と判断)しています。内部でclearIntervalを設定してsetIntervalの処理を解除しています。もしclearIntervalを設定しない場合はロード完了後も500ms毎にコンソールにwindow.googleの値が表示されます。


<template>
  <h1>Google Map</h1>
</template>

<script>
export default {
  mounted(){
    console.log(window.google)
    let timer = setInterval(() => {
      if(window.google){
        clearInterval(timer);
        console.log(window.google)
      }
    },500)
  }
}
</script>

mounted Hookの実行直後ではwindow.googleはundefinedであることがわかります。

window.googleの確認
window.googleの確認

setIntervalではなくsetTimeOutを利用してもロードの確認を行えます。setTimeOutの場合は1度だけ指定時間後に処理が実行されるのでロードが遅い場合はエラーメッセージを表示させるようにしています。


<template>
  <h1>Google Map</h1>
</template>

<script>
export default {
  mounted(){
    console.log(window.google)
    setTimeout(() => {
      if(!window.google){
        console.log('ロードに時間がかかっています。')
      }else{
        console.log(window.google)
      }
    },3000)
  }
}
</script>

Googleマップの表示

templateタグの中にGoogleマップを表示するためのdivを追加します。ref属性をつけることによりVue.jsのrefs機能を使ってVue.jsからこの要素に直接アクセスを行います。


<template>
<div>
  <h1>Google Map</h1>
  <div ref="map"></div>
</div>
</template>
refではなくidを利用してdocument.getElementByIdで要素を取得することも可能です。

windows.googleにアクセスができることを確認した後は地図を表示するためにGoogle Mapのドキュメントに記載されているものと同じ位置を指定して動作確認を行います。ブラウザで見るとオーストラリアのシドニー付近の地図が表示されます。


<template>
<div>
 <h1>Google Map</h1>
 <div ref="map" style="height:500px;width:800px;"></div>
</div>
</template>

<script>
export default {
  data(){
    return {
      map:'',
    }
  },
  mounted(){
    let timer = setInterval(() => {
      if(window.google){
        clearInterval(timer);
        this.map = new window.google.maps.Map(this.$refs.map, {
          center: {lat: -34.397, lng: 150.644},
          zoom: 8
        });       
      }
    },500)
  }
}
</script>
GoogleMapがブラウザ上に表示
GoogleMapがブラウザ上に表示

もしsetIntervalを利用していない場合でアクセス時にwindow.googleがundefinedの場合は地図は表示されずコンソールにエラーメッセージが表示されます。

window.googleにアクセスできないためエラー
window.googleにアクセスできないためエラー

Googleマップにマーカーを表示

マップで指定した位置にマーカーを表示します。位置はデータプロパティのmyLatLngに保存しています。window.google.maps.Markerの引数のオブジェクトに位置と表示するmapを指定しています。


<template>
  <div>
    <h1>Google Map</h1>
    <div ref="map" style="height: 500px; width: 800px"></div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      myLatLng: { lat: -34.397, lng: 150.644 },
    };
  },
  mounted() {
    let timer = setInterval(() => {
      if (window.google) {
        clearInterval(timer);
        const map = new window.google.maps.Map(this.$refs.map, {
          center: this.myLatLng,
          zoom: 8,
        });
        new window.google.maps.Marker({
          position: this.myLatLng,
          map,
        });
      }
    }, 500);
  },
};
</script>

ブラウザで確認すると地図上にマーカーを確認することができます。Vue.jsとGoogle Mapを利用して指定した位置の地図をブラウザ上に表示できるようになりました。

マップ上にMakerを表示
マップ上にMakerを表示

scriptタグを動的に作成する方法

先ほどの設定ではscriptタグをindex.htmlに貼り付けていましたが、index.htmlに貼り付けるということはGoogleMapが利用されていないページにアクセスしてもGoogle Mapのライブラリをダウンロードすることになります。マップを表示するコンポーネントのみGoogle Mapのライブラリをダウンロードできるようにページに動的にscriptタブを追加する方法を確認します。

動的に追加する方法もGoogleのドキュメントに記載されているのでそのコードを参考にしています。

先ほどindex.htmlに追加したGoogle mapのscriptタグを削除してから行います。

document.createElementでscriptタグの要素を作成し、document.head.appendChildで作成したscriptタグをheadタグの中に追加してします。残りのコードの変更はありません。


<template>
  <h1>Google Map</h1>
  <div ref="map" style="height: 500px; width: 800px"></div>
</template>

<script>
export default {
  data() {
    return {
      myLatLng: { lat: -34.397, lng: 150.644 },
    };
  },
  mounted() {
    const script = document.createElement('script');
    script.src =
      'https://maps.googleapis.com/maps/api/js?key=YOUR_MAP_KEY';
    script.async = true;
    document.head.appendChild(script);
    let timer = setInterval(() => {
      if (window.google) {
        clearInterval(timer);
        const map = new window.google.maps.Map(this.$refs.map, {
          center: this.myLatLng,
          zoom: 8,
        });
        new window.google.maps.Marker({
          position: this.myLatLng,
          map,
        });
      }
    }, 500);
  },
};
</script>

ブラウザをリロードすると先ほどと同様にブラウザ上にマップが表示されていることを確認することができます。

動的にscriptタグを追加してマップ表示
動的にscriptタグを追加してマップ表示

scrpitタグのloadイベントを利用することでライブラリのロードの完了を確認することができます。イベントリスナーを利用した場合には下記のように記述することができます。addEventlistnerで’load’イベントを監視、ロードが完了したらwindow.googleにアクセスすることができるのでGoogle Mapの描写の処理を行います。


export default {
  data() {
    return {
      myLatLng: { lat: -34.397, lng: 150.644 },
    };
  },
  mounted() {
    const script = document.createElement('script');
    script.src =
      'https://maps.googleapis.com/maps/api/js?key=YOUR_MAP_KEY';
    script.async = true;
    script.addEventListener('load', () =< {
      const map = new window.google.maps.Map(this.$refs.map, {
        center: this.myLatLng,
        zoom: 8,
      });
      new window.google.maps.Marker({
        position: this.myLatLng,
        map,
      });
    });
    document.head.appendChild(script);
  },
};

callbackのinitMapを利用する方法

scriptタグの後ろについていたcallback=initMapを追加することでマップを表示することができるか確認を行います。

initMapを実行するためにコードの中では、windowをつけてwindow.initMapとする必要があります。initMapでは実行することはできません。Google Mapのライブラリのロードが完了してからinitMapは実行されるのでsetIntervalを利用する必要がなくなります。


export default {
  data() {
    return {
      myLatLng: { lat: -34.397, lng: 150.644 },
    };
  },
  mounted() {
    const script = document.createElement('script');
    script.src =
      'https://maps.googleapis.com/maps/api/js?key=YOUR_MAP_KEY';
    script.async = true;
    document.head.appendChild(script);

    window.initMap = () => {
      const map = new window.google.maps.Map(this.$refs.map, {
        center: this.myLatLng,
        zoom: 8,
      });
      new window.google.maps.Marker({ position: this.myLatLng, map });
    };
  },
};

複数のコンポーネントを同時に表示

scriptタグを動的に作成する方法ではコンポーネント毎にscriptタグを作成してためコンソールに下記のメッセージが表示されます。1つのページに複数回Google Maps JavaScript APIが含まれているというエラーです。ブラウザ上にはマップは表示されます。

You have included the Google Maps JavaScript API multiple times on this page. This may cause unexpected errors
Vue Routerを利用している場合に移動先のページでもGoogle Mapコンポーネントを利用している場合はページを移動する度にscriptタグが追加されていくので同様のエラーメッセージが表示されます。

デベロッパーツールからElementsを見ると2つのGoogleMapコンポーネントを1つのページに2つ使っている場合は、headタグの中に2つのscriptタグが挿入されていることが確認できます。

index.htmlにscriptタグを追加する場合はこの問題は発生しません。

1つのページ複数のscriptタグ(Google Map)が追加される問題を解決するためには複数回scriptタグが登録されない仕組みを組み込む必要があります。

下記に問題に対応したコードを記述していますが、複数のscriptタグを追加しないようにwindowオブジェクトにmapLoadStartedという変数を設定して1つのコンポーネントのみでscriptタグ追加のコードを実行するように制御しています。他のmapLoadStartedはGoogle Mapライブラリのロードを開始したよという意味を持ち最初に実行したコンポーネントの時はmapLoadStartedはundefinedなのでscriptの追加の処理が実行されます。それ以後はmapLoadStartedの値はtrueとなりscriptタグ追加の処理が行われることはありません。


export default {
  data() {
    return {
      myLatLng: { lat: -34.397, lng: 150.644 },
    };
  },
  mounted() {
    if (!window.mapLoadStarted) {
      window.mapLoadStarted = true;
      let script = document.createElement('script');
      script.src =
        'https://maps.googleapis.com/maps/api/js?key=-YOUR_MAP_KEY&callback=initMap';
      script.async = true;
      document.head.appendChild(script);
    }

    window.initMap = () => {
      window.mapLoaded = true;
    };

    let timer = setInterval(() => {
      if (window.mapLoaded) {
        clearInterval(timer);
        const map = new window.google.maps.Map(this.$refs.map, {
          center: this.myLatLng,
          zoom: 4,
        });
        new window.google.maps.Marker({ position: this.myLatLng, map });
      }
    }, 500);
  },
};

次にwindowオブジェクトにmapLoadedという変数を設定しています。Google Mapライブラリのロードが完了したら実行されるinitMap関数を使ってmapLoadedの値をtrueにしています。trueになっている場合はロードが完了しているのでマップの描写の処理を行うことができます。setIntervalを利用してGoogle Mapのライブラリのロードが完了しているのかチェックを行なっています。mapLoadedがtrueの場合のみ地図の描写の処理が行われます。

windowオブジェクトにmapLoadedを加えることで”You have included the Google Maps JavaScript API multiple times on this page. This may cause unexpected errors”は解消します。Vue Routerを利用してページを移動する場合にmapLoadedを使っていない場合はGoogleMapコンポーネントを利用しているページに移動する度にscriptタグが追加されエラーが発生しましたが設定後はエラーは解消されました。

propsを使ってマップの位置を変更

GoogleMapコンポーネントにpropsを追加し、表示するマップの場所を変更できるように更新します。またzoomで表示する地図の拡大・縮小率も変更できるようにします。

propsを使って親コンポーネントからmyLatLngとzoomの値を受け取ります。


export default {
  props: {
    myLatLng: {
      type: Object,
      required: true,
    },
    zoom: {
      type: Number,
      required: true,
    },
  },
  mounted() {
    if (!window.mapLoadStarted) {
      window.mapLoadStarted = true;
      let script = document.createElement('script');
      script.src =
        'https://maps.googleapis.com/maps/api/js?key=YOUR_MAP_KEY&callback=initMap';
      script.async = true;
      document.head.appendChild(script);
    }

    window.initMap = () => {
      window.mapLoaded = true;
    };

    let timer = setInterval(() => {
      if (window.mapLoaded) {
        clearInterval(timer);
        const map = new window.google.maps.Map(this.$refs.map, {
          center: this.myLatLng,
          zoom: 4,
        });
        new window.google.maps.Marker({ position: this.myLatLng, map });
      }
    }, 500);
  },
};

GoogleMapコンポーネントをimportしている親コンポーネントのApp.vueではpropsで経度と緯度とzoomの値を渡します。


<template>
  <div>
    <google-map :myLatLng="{lat: -25.344, lng: 131.036}" :zoom="4" />
  </div>
</template>

先ほどとは異なる場所を指定したのでオーストラリアのウルルを中心としたマップが表示されます。

propsで値を渡してマップを表示
propsで値を渡してマップを表示

他にもGoogle Mapにはオプションが存在しますがここまでの基礎的な設定を理解したことで使いこなすことができるようになっているはずです。

Pluginsの作成

ここまでの動作確認を通してコンポーネントへのGoogleMapの追加方法は理解できたかと思います。ここではこれまでの作成したコードを利用しながらVueのPluginを作成していきます。Vueで初めてPluginを作成する人は以下の文書を参考になるかと思います。

Pluginsの動作確認

srcフォルダにプラグインを保存するフォルダpluginsを作成し、その下にGoogleMap.jsファイルを作成します。ファイルの名前は任意なので好きな名前をつけてください。

プラグインを利用できるようにmain.jsファイルにプラグイン追加のコードを追加します。


import { createApp } from 'vue';
import App from './App.vue';
import GoogleMap from './plugins/GoogleMap';

const app = createApp(App);
app.use(GoogleMap);
app.mount('#app');

Pluginが問題なく読み込まれるのか確認するためにGoogleMap.jsファイルに以下を記述します。


const GoogleMap = {
  install(app) {
    console.log(app);
  },
};
export default GoogleMap;

App.vueファイルは後ほど利用するGoogleMapをコメントアウトしておきます。


<template>
  <h1>プラグインの作成</h1>
  <!-- <google-map />> -->
</template>

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

export default {
  name: 'App',
  // components: {
  //   GoogleMap,
  // },
};
</script>

ブラウザのデベロッパーツールのコンソールを見るとVueのインスタンスに関する情報が表示されます。

Pluginsの動作確認でappの中身を表示
Pluginsの動作確認でappの中身を表示

プラグインからscriptタグを追加

プラグインファイルにscriptタグを追加するコードを記述します。GoogleMapのcallbackのinitMap関数の設定は行っていませんが下記のコードを追加するとheadタグにscriptタグが追加されます。ブラウザでデベロッパツールの要素を確認することでscriptタグの追加を確認できます。


const GoogleMap = {
  install() {
    const loadScript = () => {
      let script = document.createElement('script');
      script.src =
        'https://maps.googleapis.com/maps/api/js?key=YOUR_MAP_KEY&callback=initMap';
      script.async = true;
      document.head.appendChild(script);
    };

    loadScript();
  },
};
export default GoogleMap;

initMap関数の追加

initMap関数とmapLoaded変数を追加します。ライブラリのロードが完了してinitMap関数が実行されmapLoadedの値がfalseからtrueになることを確認しています。


const GoogleMap = {
  install() {
    let mapLoaded = false;
    const loadScript = () => {
      let script = document.createElement('script');
      script.src =
        'https://maps.googleapis.com/maps/api/js?key=KIaSyBbbEUWqwVYWapRl2AZJ8X-9_vibRDvpao&callback=initMap';
      script.async = true;
      document.head.appendChild(script);
    };

    loadScript();

    window.initMap = () => {
      mapLoaded = true;
      console.log(mapLoaded);
    };
  },
};
export default GoogleMap;

ブラウザで確認するとコンソールにtrueが表示されます。

メソッドの追加

Vueコンポーネントからプラグインファイルで定義したメソッドを実行するために$showMapというメソッドを追加します。コンポーネントからはthis.$showMapでプラグインの中のメソッドを実行できるようになります。メソッドを追加する場合は以下のように記述します。


app.config.globalProperties.$showMap = () => {
  console.log('$showMap');
};

App.vueファイルにmountedフックを追加してthis.$showMapが実行できるか確認します。


<template>
  <h1>プラグインの作成</h1>
  <!-- <google-map />> -->
</template>

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

export default {
  name: 'App',
  // components: {
  //   GoogleMap,
  // },
  mounted() {
    this.$showMap();
  },
};
</script>

ブラウザのコンソールに$showMapの文字列が表示されればメソッドは実行されていることになります。

Google Mapを表示する処理

GoogleMapを表示するdiv要素と位置情報の2つの引数を取るshowMap関数を追加します。showMap関数の中でGoogle Mapを描写する処理を実行します。


const showMap = (canvas, myLatLng) => {
  const map = new window.google.maps.Map(canvas, {
    center: myLatLng,
    zoom: 4,
  });
  new window.google.maps.Marker({ position: myLatLng, map });
};

showMap関数はGoogle Mapのライブラリが完了した場合のみ実行するように$showMap関数の中に処理を追加します。


app.config.globalProperties.$showMap = (canvas, myLatLng) => {
  if (mapLoaded) {
    showMap(canvas, myLatLng);
  }
};

コンポーネントから$showMapを実行しmapLoadがtrueの場合のみshowMap関数が実行されることになります。$showMap関数は引数にGoogleMapを表示するdiv要素と位置情報の2つの引数を取ります。

App.vueファイルにGoogleMapを表示させるGoogleMapコンポーネントをimportします。


<template>
  <h1>プラグインの作成</h1>
  <google-map />
</template>

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

export default {
  name: 'App',
  components: {
    GoogleMap,
  },
};
</script>

GoogleMap.vueファイルではmountedフックの中で$showMap関数を実行します。引数にはrefsを利用して取得したdiv要素と位置情報を設定しています。


<template>
  <h1>Google Map</h1>
  <div ref="map" style="height: 500px; width: 800px"></div>
</template>

<script>
export default {
  mounted() {
    this.$showMap(this.$refs.map, { lat: 34.344, lng: 136.036 });
  },
};
</script>

ここまでのコードで動作確認をしてもGoogle Mapは表示されません。表示されない理由は$showMapをGoogleMapコンポーネントで実行した時にライブラリのロードが完了していないためです。


app.config.globalProperties.$showMap = (canvas, myLatLng) => {
  console.log(mapLoaded);
  if (mapLoaded) {
    showMap(canvas, myLatLng);
  }
};
ライブラリのロードが早く完了されればMapが表示されることがあります。

mapLoadedがfalseの場合は実行されることはありません。mapLoadedが完了するのを待つ方法にはいくつかあると思いますが本文書でも利用したsetIntervalを利用してみましょう。mapLoadedがfalseの場合はmapLoadedがtureになるまでsetIntervalでチェックを行なっています。


app.config.globalProperties.$showMap = (canvas, myLatLng) => {
  console.log(mapLoaded);
  if (mapLoaded) {
    showMap(canvas, myLatLng);
  } else {
    let timer = setInterval(() => {
      if (mapLoaded) {
        clearInterval(timer);
        showMap(canvas, myLatLng);
      }
    }, 500);
  }
};

設定追加後ブラウザを確認すると画面にはGoogleMapコンポーネントで指定した場所の地図が表示されるはずです。

プラグインを使って表示した地図
プラグインを使って表示した地図

作成したプラグインのコードは下記の通りです。


const GoogleMap = {
  install(app) {
    let mapLoaded = false;
    const loadScript = () => {
      let script = document.createElement('script');
      script.src =
        'https://maps.googleapis.com/maps/api/js?key=AIzaSyBFbEUWqfdfeaYWapRl2AZJ8X-9_vibRDvpao&callback=initMap';
      script.async = true;
      document.head.appendChild(script);
    };

    loadScript();

    window.initMap = () => {
      mapLoaded = true;
      console.log(mapLoaded);
    };

    const showMap = (canvas, myLatLng) => {
      const map = new window.google.maps.Map(canvas, {
        center: myLatLng,
        zoom: 4,
      });
      new window.google.maps.Marker({ position: myLatLng, map });
    };

    app.config.globalProperties.$showMap = (canvas, myLatLng) => {
      console.log(mapLoaded);
      if (mapLoaded) {
        showMap(canvas, myLatLng);
      } else {
        let timer = setInterval(() => {
          if (mapLoaded) {
            clearInterval(timer);
            showMap(canvas, myLatLng);
          }
        }, 500);
      }
    };
  },
};
export default GoogleMap;

setIntervalを利用しない方法についてのコードも作成しています。

新たにmapDataを定義し、mapLoadedがfalseの場合にcanvasとmyLatLngをmapDataに保存します。initMap関数の中でmapDataに値がある場合はmapLoadedがfalseでライブラリのロード待ちをしていたということでmapDataに値がある場合のみinitMap関数からshowMap関数を実行させています。mapLoadedがtrueの場合はshowMapが実行されるのでmapDataに値が保存されることはありません。


const GoogleMap = {
  install(app) {
    let mapLoaded = false;
    let mapData = null;
    const loadScript = () =< {
      let script = document.createElement('script');
      script.src =
        'https://maps.googleapis.com/maps/api/js?key=AIzaSyBFbEUWdaegYWapRl2AZJ8X-9_vibRDvpao&callback=initMap';
      script.async = true;
      document.head.appendChild(script);
    };

    loadScript();

    window.initMap = () =< {
      mapLoaded = true;
      if (mapData) {
        const { canvas, myLatLng } = mapData;
        showMap(canvas, myLatLng);
        mapData = null;
      }
    };

    const showMap = (canvas, myLatLng) =< {
      const map = new window.google.maps.Map(canvas, {
        center: myLatLng,
        zoom: 4,
      });
      new window.google.maps.Marker({ position: myLatLng, map });
    };

    app.config.globalProperties.$showMap = (canvas, myLatLng) =< {
      console.log(mapLoaded);
      if (mapLoaded) {
        showMap(canvas, myLatLng);
      } else {
        mapData = { canvas, myLatLng };
      }
    };
  },
};
export default GoogleMap;

Vue.jsでのGoogleMapの表示方法とプラグインの作成方法を確認することができました。