LoginSignup
3
2

More than 3 years have passed since last update.

CDNでGoogle Mapを描く

Posted at

概要

  • 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>
3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2