概要
- vueでgoogle mapを描く時のパッケージであるvue2-google-mapはGASでwebページを作成する時は使えません。
- @googlemaps/js-api-loaderというパッケージはCDNが提供されているので、これを使いました。
開発の背景
- 勤務先ではGsuitesを使って、製品検索ページやら取引先へのメール配信やらにGASを使ったWebアプリケーションを作成しています。
- GASでWebアプリを作る場合、フロント側はHTML形式で書く必要があります。普通vueやnuxtでフロントページを作る場合はwebpackでインストールしますが、GASのHTMLではwebpackは使えません。そのため、パッケージツールはCDNを頼ることになります
- Vueでgoogle mapを使うときはvue2-google-mapを使うのが一般的だと思うのですが、2021年1月現在vue2-google-mapのCDNは提供されていません。https://github.com/Jeson-gk/vue2-google-maps/blob/master/API.md
- そこで、vue2-google-mapを使うことなく、別のパッケージを使用しました。
設計
- こちらの記事を参考にしています。
https://qiita.com/terrierscript/items/9a9dda5a5ca5b3293d48
構成
- いつものnuxt風な構成にしています
layouts/default.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<?!= include("config") ?>
</head>
<body>
<?!= include("store/index") ?>
<?!= include("components/ChildMarker") ?>
<?!= include("components/MapLoader") ?>
<?!= include("pages/index") ?>
<div id="app"></div>
<script>
new Vue({
vuetify: vuetify,
store: store,
render: h => h(index)
}).$mount("#app")
</script>
</body>
</html>
pages/index.html
<script type="text/x-template" id="index">
<v-app>
<v-sheet>
<map-loader>
<template slot-scope="scopeProps">
<child-marker
v-for="(marker, i) in markers" :key="i"
:position="marker" :google="scopeProps.google" :map="scopeProps.map"/>
</template>
</map-loader>
</v-sheet>
</v-app>
</script>
<script>
const index = {
template: "#index",
components: {
"MapLoader":MapLoader,"ChildMarker":ChildMarker
},
data() {
return {
loadeds: ["お待ち下さい"],
markers:[
{"lat":35.6432027,"lng":139.6729435},
{"lat":35.5279833,"lng":139.6989209},
{"lat":35.6563623,"lng":139.7215211},
{"lat":35.6167531,"lng":139.5469376},
{"lat":35.6950961,"lng":139.5037899}
]
}
},
}
</script>
components/MapLoader.html
- ここが今回のミソです。
- templateにv-ifを書くことで、googleオブジェクトとmapオブジェクトが作られないと子コンポーネントであるChildMarkerが作られない仕組みです。
- mountedの内容はExampleに書いてあるとおりに作りました
<script type="text/x-template" id="map-loader">
<div>
<div ref="map" style="width:800px;height:500px"></div> <!-- point 1 -->
<template v-if="!!this.google && !!this.map">
<slot :google="google" :map="map"></slot>
</template>
</div>
</script>
//google mapを使うためのCDN
<script src="https://unpkg.com/@googlemaps/js-api-loader@1.0.0/dist/index.min.js"></script>
<script>
const MapLoader = {
template:"#map-loader",
data(){return{
google:null,
map:null
}},
//mountedでgoogleオブジェクトとmapオブジェクトを作成する
mounted(){
let self = this
const {Loader} = google.maps.plugins.loader
const loader = new Loader({apiKey: "API-KEY"})
const mapOption = {
center:{lat:35,lng:135},
zoom:8
}
loader
.load()
.then(()=> {
self.google = google
self.map = new google.maps.Map(self.$refs.map,mapOption)
})
.catch(e=>{
console.log(e)
})
},
}
</script>
components/ChildMarker.html
- ここのgoogleオブジェクトとmapオブジェクトは親であるMapLoaderコンポーネントから引き継いでます
<script>
const ChildMarker = {
template:"<div></div>",
props:{
google:Object,map:Object,
position:Object //{lat:Number,lng:Number}
},
data(){return{
marker:null
}},
mounted(){
const { Marker } = this.google.maps
this.marker = new Marker({
position: this.position,
map: this.map,
title: "Child marker!"
})
}
}
</script>