Create Your Own Vue3 Google Maps Component and Deploy to Mobile with Ionic Framework & Capacitor
Tags: ionic, vue, tutorial, javascript
Published: 2020-12-07 16:46:30

> [Video Series](https://dev.to/aaronksaunders/vue-google-maps-example-project-maps-markers-geocoder-api-map-resizing-adding-markers-adding-infowindow-2g26)

Create Your Own Vue3 Google Maps Component with Ionic Framework & Capacitor

{% youtube HS2wdAtCYKg %}
- More Ionic VueJS and ReactJS Video Content [FiWiC YouTube Channel](https://www.youtube.com/channel/UCMCcqbJpyL3LAv3PJeYz2bg)


Maps are a critical part of many web and mobile solutions and the rich set of functionality provided by Google Maps make it an obvious choice in many situations. When I was looking for a Vue3 compatible solution I really didn't find anything I loved so I decided to see how to roll my own.

In this video, we create a vue 3 google map component using the newer SFC component with setup. We will add marker, infoboxes, event handlers, and access to related services as we work through the project video series.

We will end each of the videos in the series by deploying the application to IOS and Android devices to showcase Ionic Capacitor which you can use to deploy any web framework mobile, web, and pwa.

ENJOY PART 1

### LINKS
- [Ionic Framework](https://ionicframework.com/docs/vue/overview) is a platform to build, secure, deploy, and scale modern native and mobile web apps across any platform. No platform unlocks more productivity. Front to back, start to finish
- [Capacitor](https://capacitorjs.com/) is an open source native runtime for building Web Native apps. Create cross-platform iOS, Android, and Progressive Web Apps with JavaScript, HTML, and CSS]
- [Google Maps Javascript API](https://developers.google.com/maps/documentation/javascript/overview) https://developers.google.com/maps/documentation/javascript/overview
- [Questions about Typescript In Google Maps]( https://developers.google.com/maps/documentation/javascript/using-typescript)

### USAGE
The component can be used in your page by first creating the `.env` file to hold your google maps key
```
VUE_APP_GOOGLEMAPS_KEY="AIzaSyDfu-PKZ1zO8POkdlrSWG36pLZEtbH5cz8"
```
and the in the parent component
```html
<g-map
  :disableUI="false"
  :zoom="12"
  mapType="roadmap"
  :center="{ lat: 38.8977859, lng: -77.0057621 }">
</g-map>
```

### SOURCE CODE
```vuejs
<template>
  <div class="map" ref="mapDivRef"></div>
</template>

<script>
import { ref, onBeforeMount, onMounted } from "vue";

export default {
  name: "GMap",
  props: {
    center: { lat: Number, lng: Number },
    zoom: Number,
    mapType: String,
    disableUI: Boolean
  },
  setup(props) {
    // the google map object
    const map = ref(null);

    // the map element in the templste
    const mapDivRef = ref(null);

    // load in the google script
    onMounted(() => {
      // key is is the .env file
      const key = process.env.VUE_APP_GOOGLEMAPS_KEY;

      // create the script element to load
      const googleMapScript = document.createElement("SCRIPT");
      googleMapScript.setAttribute(
        "src",
        `https://maps.googleapis.com/maps/api/js?key=${key}&callback=initMap`
      );
      googleMapScript.setAttribute("defer", "");
      googleMapScript.setAttribute("async", "");
      document.head.appendChild(googleMapScript);
    });

    /**
     * this function is called as soon as the map is initialized
     */
    window.initMap = () => {
      map.value = new window.google.maps.Map(mapDivRef.value, {
        mapTypeId: props.mapType || "hybrid",
        zoom: props.zoom || 8,
        disableDefaultUI: props.disableUI || false,
        center: props.center || { lat: 38.0, lng: -77.01 }
      });
    };

    return {
      mapDivRef
    };
  }
};
</script>

<style lang="css" scoped>
.map {
  width: 100%;
  height: 300px;
  background-color: azure;
}
</style>
```

<div>
  <a href="https://ko-fi.com/W7W31U7HM">
  <img src="https://www.ko-fi.com/img/githubbutton_sm.svg" data-canonical-src="https://www.ko-fi.com/img/githubbutton_sm.svg"  height="30" alt="Medium" /></a>
 </div>