Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

CDNでGoogle Mapを描く

概要

  • 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>
w5966qzh
32歳、未経験だった僕が趣味と教養のためにプログラミングを始めてます。 ノート代わりにQiitaを書いてます。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away