やりたいこと
一般的にGoogle map api をwebアプリケーションで使おうとしたとき、例えば以下のような感じで利用する。
- html
<!DOCTYPE html> <html> <head> <title>Simple Map</title> <style> #map { height: 100%; width: 100%; } </style> <script src="https://maps.googleapis.com/maps/api/js?key={API_KEY}&callback=initMap&libraries=places&v=weekly"></script> <script> function initMap(){ const map = new google.maps.Map(document.getElementById("map"), { zoom:10, center: new google.map.LatLng(-34.397, 150.644) } } </script> </head> <body> <div id="map"></div> </body> </html>
一般的なライブラリはnpm/yarn
経由でモジュールが提供されており、その場合は特に迷うことなく使えたのだが、google map api はweb api を叩くしか方法がなさそうだった。
今回のケースのようにCDN経由でライブラリを利用する場合はVue.jsをどうやって利用するのかがわからなかったため、その実装方法について調べてみた。
結論
- cdnライブラリを使用するときと同様にscriptタグを動的に書き込むしかない
ちなみにいくつか試してみたが、以下はだめだった
- httpクライアントで直接getリクエストする
→ クロスドメインリクエスト(CORS)が許可されていないため、使用不可。
- コンポーネントのtemplate要素にscriptタグを予め書き込む
→ Vue.jsではtemplate要素内にscripタグを書くことはできないため、使用不可。
また細かい話として、google map apiの場合は、リクエストパラメータにコールバック関数名を引き渡すことで、ロード後に初期化するようにしている。
具体的なコードは以下のような感じ。(Nuxt.jsを利用しているためVueインスタンスのマウント部分はない)
- pages/index.vue
<template> <div id="map"></div> </template> <script> import qs from query-string' const params = { key: {your-APIkey}, libraries: 'places', v: 'weekly', callback: 'handleLoadGoogleMapScript' } export default { data(){ return google: null }, mounted(){ const mapDiv = document.getElementById('map') this.loadGoogleMapScript().then(google => { this.google = google this.initMap(mapDiv) }) }, methods{ loadGoogleMapScript(){ return new Promise((resolve, reject) => { if(window.google){ return resolve(window.google) }else{ const script = document.createElement('script') script.src = `https://maps.googleapis.com/maps/api/js?${qs.stringfy(params)}` const head = document.getElementsByTagName('head')[0] if(!head){ return reject(new Error('head tag is not load')) }else{ head.appendChild(script) window.handleLoadGoogleMapScript = () => { return resolve(window.google) } } setTimeout(() => { if (!window.google){ reject(new Error('Failed to load google map api)) } }, 5*1000) } }) } }, } </script>