Integrando Ionic Framework 4 con Google maps
Tags: ionic, learning, spanish, googlemaps
Published: 2019-05-31 07:07:20

---
title: Integrando Ionic Framework 4 con Google maps
published: true
description: Post de refuerzo al curso de Ionic Framework que imparto en @ecudevs
tags: Ionic,learning,spanish,GoogleMaps
---

Este es mi primer post en Dev.to, y es un complemento al <a href="https://www.ecudevs.com/cursos/ionic" target="_blank">curso</a> de Ionic Framework que dicto en Ecudevs.

En esta ocasión vamos a integrar nuestra aplicación hecha en <a href="https://ionicframework.com/" target="_blank">Ionic Framework</a> con el api de Google Maps. Debido a que este post va como refuerzo al curso vamos a trabajar con el código fuente resultante de la pequeña aplicación que desarrollamos en el transcurso del mismo, por lo que puedes clonar el siguiente repositorio:
{% github ecudevs/ionic-5 %}
Esta es una pequeña app que realiza el mantenimiento de una colección de una base de datos de <a href="https://www.mongodb.com/es" target="_blank">MongoDB</a>.

Una vez clonado nuestro repositorio y haber instalado todas las dependencias nos ponemos manos a la obra.

# 1. Obtén un api key de Google
Lo primero que debes hacer es obtener un Api Key de Google Maps y esto lo hacemos desde el <a href="https://console.cloud.google.com" target="_blank">Cloud Console de Google</a>, accede con tu cuenta de Google y crea un nuevo proyecto.

![Google Console](https://thepracticaldev.s3.amazonaws.com/i/o0pw2wgg9e5xmvjlau10.PNG)

Después de haber creado tu proyecto accede a la biblioteca de APIs en el menú lateral.

![Acesso a la biblioteca de APIs](https://thepracticaldev.s3.amazonaws.com/i/hjh2gtse7uqc5tu76u2n.png)

Aquí busca y selecciona la opción *Maps SDK for Android* y habilita esta API.

Luego, en el apartado de credenciales, damos clic en "Crear credenciales" y seleccionamos la opción API key.

![Crear una credencial](https://thepracticaldev.s3.amazonaws.com/i/9kc1kddnpf03qhim6u2v.png)

Automáticamente este proceso nos genera un key el cual por el momento lo vamos a guardar en un lugar seguro para luego utilizarlo, por lo que finalmente vamos a cerrar el cuadro de dialogo que se desplegó.

![API key generado](https://thepracticaldev.s3.amazonaws.com/i/gsf1aezddmwiy43glhfs.png)

# 2. Integración con Ionic Native
<a href="https://ionicframework.com/docs/native" target="_blank">Ionic Native</a> es una herramienta que sirve para agregar funcionalidad nativa a nuestra aplicación de Ionic a través de <a href="https://cordova.apache.org/" target="_blank">Cordova</a>.

En este caso, nosotros, para los mapas de google vamos a usar un plugin llamado <a href="https://github.com/ionic-team/ionic-native-google-maps" target="_blank">ionic-native-google-maps</a>, el cual lo podemos instalar a través de npm e Ionic CLI con los siguientes comandos:

```bash
npm install @ionic-native/core@beta @ionic-native/google-maps@beta


ionic cordova plugin add https://github.com/mapsplugin/cordova-plugin-googlemaps#multiple_maps
```

Una vez instaladas las dependencias para nuestro mapa de Google, tenemos que ir a nuestro archivo *config.xml* y justo después del último nodo de preferencias pegamos lo siguiente reemplazando el valor de el API KEY que obtuvimos en el primer paso:

```xml
<preference name="GOOGLE_MAPS_ANDROID_API_KEY" value="NUESTRO_API_KEY" />
```

Y nuestro código debería quedar algo así:

![config.xml](https://thepracticaldev.s3.amazonaws.com/i/rxdi5n6o1ibgb0w7q485.PNG)

Con nuestras configuraciones listas, vamos a lo que verdaderamente nos concierne, a nuestro código.

# 3. A programar nuestro mapa

Nuestro proyecto extiende del template de tipo *Tabs* que nos ofrece Ionic CLI al momento de generarlo, y toda la programación hasta este momento se centra en solo un tab que es el *tab1*, nuestro mapa de Google lo vamos a programar en el *tab2*.

Lo primero que debemos hacer es darle forma a nuestra vista por lo que nos vamos a centrar en los archivos html y scss de nuestro componente *tab2*, y dentro de la etiqueta `<ion-content>` vamos a ubicar lo siguiente.

```html
  <div id="map_canvas"></div>
  <ion-fab vertical="bottom" horizontal="end" slot="fixed">
    <ion-fab-button color="danger" (click)="localizar()">
      <ion-icon name="pin"></ion-icon>
    </ion-fab-button>
  </ion-fab>
```

Nuestro código debería quedar algo parecido a esto:
![tab2.page.html](https://thepracticaldev.s3.amazonaws.com/i/dphap38xh5f28cs1x4j1.PNG)

El primer *div* que agregamos a nuestra vista se refiere al espacio donde nuestro  mapa será renderizado. A este *div* debemos configurar ciertos estilos para en este caso estos estilos que vamos agregar harán que nuestro mapa ocupe la totalidad de la pantalla, entonces para eso vamos a el archivo scss de este componente y agregamos lo siguiente:

```scss
#map_canvas {
  width: 100%;
  height: 100%;
}
```

No olvides configurar estos estilos, ya que, si no, el mapa no se va a mostrar en la pantalla.

Regresando a nuestra vista, el siguiente elemento que agregamos después del *div* que contiene al mapa, es un simple `ion-fab` que ejecutará el método `localizar()` del componente, esta función hará que se muestre nuestra ubicación en el mapa.

Es el turno de trabajar en el controlador de esta vista, vamos al archivo `tab2.page.ts` en donde deberemos agregar el siguiente código:

```typescript
import { Component, OnInit } from "@angular/core";

import {
  GoogleMaps,
  GoogleMap,
  GoogleMapsEvent,
  Marker,
  GoogleMapsAnimation,
  MyLocation
} from "@ionic-native/google-maps";

import { Platform, LoadingController, ToastController } from "@ionic/angular";

@Component({
  selector: "app-tab2",
  templateUrl: "tab2.page.html",
  styleUrls: ["tab2.page.scss"]
})
export class Tab2Page implements OnInit {
  map: GoogleMap;
  loading: any;

  constructor(
    public loadingCtrl: LoadingController,
    public toastCtrl: ToastController,
    private platform: Platform
  ) {}

  async ngOnInit() {
    // Debido ngOnInit() inicia antes del evento
    // deviceready, debemos detectar cuando este evento se
    // ejecute para en ese momento cargar nuestro mapa sin problema alguno
    await this.platform.ready();
    await this.loadMap();
  }

  loadMap() {
    // Esta función inicializa la propiedad de clase
    // map
    // que va a contener el control de nuestro mapa de google

    // Para crear nuestro mapa debemos enviar como parametros
    // el id del div en donde se va a renderizar el mapa (paso anterior)
    // y las opciones que configuran nuestro mapa
    this.map = GoogleMaps.create("map_canvas", {
      camera: {
        target: {
          lat: -2.1537488,
          lng: -79.8883037
        },
        zoom: 18,
        tilt: 30
      }
    });
  }

  async localizar() {
    // Limpiamos todos los elementos de nuestro mapa
    this.map.clear();

    // Creamos un componente de Ionic para mostrar un mensaje
    // mientras obtenemos esperamos que termine el proceso de
    // obtener la ubicación
    this.loading = await this.loadingCtrl.create({
      message: "Espera por favor..."
    });

    // Presentamos el componente creado en el paso anterior
    await this.loading.present();

    // Ejecutamos el método getMyLocation de nuestra propiedad de clase
    // map
    // para obtener nuestra ubicación actual
    this.map
      .getMyLocation()
      .then((location: MyLocation) => {
        // Una vez obtenida la ubicación cerramos el mensaje de diálogo
        this.loading.dismiss();

        // Movemos la camara a nuestra ubicación con una pequeña animación
        this.map.animateCamera({
          target: location.latLng,
          zoom: 17,
          tilt: 30
        });

        // Agregamos un nuevo marcador
        let marker: Marker = this.map.addMarkerSync({
          title: "Estoy aquí!",
          snippet: "This plugin is awesome!",
          position: location.latLng,
          animation: GoogleMapsAnimation.BOUNCE
        });

        // Mostramos un InfoWindow
        marker.showInfoWindow();

        // Podemos configurar un evento que se ejecute cuando
        // se haya dado clic
        marker.on(GoogleMapsEvent.MARKER_CLICK).subscribe(() => {
          this.showToast("clicked!");
        });
      })
      .catch(error => {
        // En caso de que haya un problema en obtener la
        // ubicación
        this.loading.dismiss();
        this.showToast(error.error_message);
      });
  }

  // Función que muestra un Toast en la parte inferior
  // de la pantalla
  async showToast(mensaje) {
    let toast = await this.toastCtrl.create({
      message: mensaje,
      duration: 2000,
      position: "bottom"
    });

    toast.present();
  }
}
```

## Propiedad `map`
Nuestra clase posee una propiedad *`map`* la cual contendrá toda la información y métodos de nuestro mapa de Google como tal, entonces lo primero que debemos hacer es crear una nueva instancia de mapa apenas iniciado nuestro componente, para hacer tal cosa implementamos la interfaz `OnInit` y al mismo tiempo el método `ngOnInit()` y es exactamente aquí donde debe ir toda la lógica que crea mi mapa, esta lógica va a ser invocada desde un método llamado `loadMap()`. Pero bien, antes de la llamada a esta función debemos asegurarnos de que la plataforma que está ejecutando nuestro código está lista y poder invocar funcionalidad nativa, para de esta manera no tener problemas al cargar nuestro mapa, esto lo hacemos mediante un `service` propio de Ionic llamado <a href="https://ionicframework.com/docs/utilities/platform" target="_blank">Platform</a>, service que posee un método `ready()` que me va a devolver una `promesa` cuando nuestra plataforma esté lista.

## loadMap()
Este método realiza la creación de nuestro mapa como tal a través del método `create` de la clase `GoogleMaps`. El método `create` recibe como primer parámetro el `Id` del *div* donde va a renderizar nuestro mapa y como segundo parámetro un objeto que debe implementar la interfaz <a href="https://github.com/ionic-team/ionic-native-google-maps/blob/master/documents/googlemapoptions/README.md" target="_blank">`GoogleMapOptions`</a>, en este caso pasamos a través de este objeto una propiedad `camera` en donde a su vez configuramos parámetros acerca de donde queremos que se ubique nuestro mapa, es decir la longitud y latitud, también configuramos el zoom y el ángulo de la vista (tilt).

## localizar()
En este método vamos a hacer que nuestro mapa obtenga nuestra ubicación actual y mostraremos un pequeño marcador al cual configuraremos un evento que se va a ejecutar cuando demos clic en el mismo.

Primero dejamos limpio nuestro mapa de todos los elementos gráficos que este pudiera tener con el método `this.map.clear()`, luego mostramos un pequeño diálogo para que nuestro usuario no desespere mientras obtenemos la ubicación.

```typescript
 this.map.clear();

 this.loading = await this.loadingCtrl.create({
  message: "Espera por favor..."
 });

await this.loading.present();
```

Luego ejecutamos el método `getMyLocation()` de nuestro objeto `map` el cual me va a devolver una promesa cuando se haya obtenido la ubicación.

```typescript
this.map.getMyLocation()
 .then((location: MyLocation) => {
        ...
  })
 .catch(error => {
        ...
 });
```

Una vez que obtuvimos la información de nuestra ubicación vamos a movernos en el mapa a través de `this.map.animateCamera`, método al que debemos enviar información muy parecida a la que le enviamos por default a nuestro mapa, con la diferencia de que la longitud y latitud va a ser la que hemos obtenido.

```typescript
this.map.animateCamera({
 target: location.latLng,
 zoom: 17,
 tilt: 30
});
```

Con nuestra vista situada en la ubicación obtenida vamos a dibujar un nuevo marcador, configurando un título, un pequeño texto de descripción, la posición y una pequeña animación `GoogleMapsAnimation.BOUNCE` la cual hará que al dibjuarse el marcador dispare una animación de rebote.

```typescript
let marker: Marker = this.map.addMarkerSync({
 title: "Estoy aquí!",
 snippet: "This plugin is awesome!",
 position: location.latLng,
 animation: GoogleMapsAnimation.BOUNCE
});
```

Y por último configuramos el evento clic en nuestro marcador haciendo que se muestre un toast cuando este se dispare.

```typescript
marker.on(GoogleMapsEvent.MARKER_CLICK).subscribe(() => { 
 this.showToast("clicked!"); 
});
```

![Resultado final](https://thepracticaldev.s3.amazonaws.com/i/zaudo0vlgc6kq6xf60z7.gif)

# Conclusión
El uso de los mapas de Google es una práctica muy común hoy en día, la importancia de referenciar ubicaciones, lugares se vuelve parte de nuestro día a día, y es por esta razón que en nuestro programa abarcamos este tema, espero que haya sido de bastante ayuda y no olvides tu like y comentarios, que nos ayudan mucho para mejorar.