Ionic y Google Maps, seleccionar una ubicación

En este post vamos crear una aplicación con Ionic donde vamos a poder seleccionar una ubicación en Google Maps, por defecto el mapa lo vamos a ubicar en la posición en la que nos encontremos a la hora de abrir la aplicación, para ello vamos a utilizar Ionic Native con el plugin de Cordova llamado Geolocation.

Antes de seguir con este post les recomiendo ver un post anterior sobre cómo utilizar plugins de Cordova con Ionic Native.

Crear el proyecto

Para empezar vamos a crear la estructura del proyecto. Utilizando el Ionic CLI, ejecutamos en la consola:

ionic start demoGoogleMaps blank

Vamos a utilizar la plantilla blank pues es una aplicación sencilla que va a mostrar el mapa y permitir seleccionar una ubicación, por lo tanto sólo va a tener una pantalla.

Creando el proyecto demoGoogleMaps
Creando el proyecto demoGoogleMaps

Mapas

Vamos a empezar por implementar todo lo que necesitamos para manejar la ubicación del usuario y Google Maps.

Antes de seguir vamos a necesitar una API Key de Google Maps, si no tienes alguno puedes seguir estos pasos para obtener uno.

Para obtener la ubicación actual del usuario necesitamos importar un plugin de Apache Cordova llamado Geolocation, para ello ejecutamos el siguiente comando en la consola, dentro de la carpeta del proyecto:

ionic cordova plugin add cordova-plugin-geolocation

Si al ejecutar este comando nos pregunta algo como “The plugin @ionic/cli-plugin-cordova is not installed. Would you like to install it and continue?” respondemos que si “Y”, esto es debido a que el nuevo CLI de Ionic está separado en módulos por lo que nos pregunta si deseamos instalar el módulo relacionado a comandos de Apache Cordova. Luego necesitamos instalar la librería de Ionic Native encargada de manejar este plugin:

npm install --save @ionic-native/geolocation

Listo, el próximo paso es crear un proveedor encargado de manejar las interacciones con Google Maps, vamos a crear el proveedor utilizando el CLI de Ionic:

ionic g provider GoogleMaps

Este comando nos va a crear el proveedor en src/providers/google-maps/google-maps.ts, cuyo código vamos a reemplazar con el siguiente:


import { Injectable } from '@angular/core';
import { Geolocation } from '@ionic-native/geolocation';
declare var google;
@Injectable()
export class GoogleMaps {
mapElement: any;
map: any;
marker: any;
apiKey: string = "AIzaSyA3uv4zlpr1Yi4Hb0h7rB7xXLNiePeBEc0";
centerChangedCallback: any;
constructor(public geolocation: Geolocation) {
}
init(mapElement: any, centerChangedCallback: any): Promise<any> {
this.mapElement = mapElement;
this.centerChangedCallback = centerChangedCallback;
return this.loadMap();
}
loadMap(): Promise<any> {
return new Promise((resolve) => {
if (typeof google == 'undefined' || typeof google.maps == "undefined") {
window['mapInit'] = () => {
this.initMap().then(() => {
resolve(true);
});
}
let script = document.createElement("script");
script.id = "googleMaps";
if (this.apiKey) {
script.src = 'http://maps.google.com/maps/api/js?key=&#39; + this.apiKey + '&callback=mapInit';
} else {
script.src = 'http://maps.google.com/maps/api/js?callback=mapInit&#39;;
}
document.body.appendChild(script);
} else {
resolve(true);
}
});
}
initMap(): Promise<any> {
return new Promise((resolve) => {
this.geolocation.getCurrentPosition().then((position) => {
let center = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
let mapOptions = {
center: center,
zoom: 17,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
this.map = new google.maps.Map(this.mapElement, mapOptions);
this.map.addListener('click', e => {
this.map.panTo(e.latLng);
if (this.marker == undefined) {
this.marker = new google.maps.Marker({
map: this.map,
position: e.latLng
});
} else {
this.marker.setPosition(e.latLng);
}
if (this.centerChangedCallback)
this.centerChangedCallback(e.latLng);
});
resolve(true);
});
});
}
}

view raw

google-maps.ts

hosted with ❤ by GitHub

  • El método init() lo utilizamos para configurar el proovedor pues el mismo recibe el elemento donde se va a mostrar el mapa en la pantalla “mapElement” y el callback que vamos a ejecutar cada vez que cambie el centro del mapa “centerChangedCallback”. Finalmente ejecuta el método loadMap().
  • El método loadMap() vamos a utilizarlo para configurar el API de Google Maps, para ello primero chequeamos que el API de Google Maps esté cargado chequeando que el objeto google no esté indefinido. De no estar listo el API tenemos que configurarlo, para ello adicionamos un elemento script a la página al cual asignamos la URL del API de Google Maps a la cual le configuramos el apiKey (si es que tenemos uno) y la función callback que queremos ejecutar cuando se cargue el API, dicha funcion “mapInit” la configuramos en la línea 27 y lo que hace es ejecutar el método initMap() de nuestro proovedor.
  • El método initMap() lo utilizamos para finalmente manejar el mapa. Primero debemos obtener la posición inicial del usuario lo cual hacemos en la línea 51 utilizando el plugin Geolocation. Teniendo la ubicación lo que queda es utilizar el API de Google Maps para mostrar el mapa, en este caso la versión Javascript del API sobre la cual pueden leer en la documentación en Google. Lo más importante de destacar aquí es el Map listener (es como un evento) que configuramos en la línea 61, con el cual, utilizando el método panTo() del mapa, movemos el mismo hacia la posición donde hicimos click y luego ponemos el marcador en dicha posición (o actualizamos la posición del marcador si ya lo habíamos puesto en otro sitio antes.

No olvides cambiar el valor de la propiedad apiKey con tu API Key de Google Maps.

Debemos ahora modificar el módulo raíz de la aplicación AppModule para registrar ambos proveedores Geolocation (importado desde Ionic Native) y GoogleMaps:


import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { Geolocation } from '@ionic-native/geolocation';
import { GoogleMaps } from '../providers/google-maps/google-maps';
@NgModule({
declarations: [
MyApp,
HomePage
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage
],
providers: [
StatusBar,
SplashScreen,
Geolocation,
{ provide: ErrorHandler, useClass: IonicErrorHandler },
GoogleMaps
]
})
export class AppModule { }

Seleccionando ubicación en el mapa

Ya que tenemos todo lo necesario para implementar la funcionalidad deseada, vamos a modificar la vista de la página src/pages/home/home.html:


<ion-header>
<ion-navbar>
<ion-title>
Ionic Blank
</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<div #map id="map">
<ion-spinner></ion-spinner>
</div>
</ion-content>

Lo único relevante de destacar en este código es que adicionamos un elemento div donde se va a mostrar el mapa y dentro del mismo adicionamos un spinner de Ionic utilizando la directiva ion-spinner, lo cual permitirá que se muestre dicho spinner mientras de carga el mapa.

También vamos a modificar la hoja de estilos src/pages/home/home.scss perteneciente a esta pantalla de modo que el mapa pueda ocupar toda la pantalla:


page-home {
.scroll-content {
overflow: hidden;
}
#map {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}

Finalmente modificamos el código del componente/controlador de la pantalla en src/pages/home/home.ts:


import { Component, ViewChild, ElementRef } from '@angular/core';
import { GoogleMaps } from '../../providers/google-maps/google-maps';
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
@ViewChild('map') mapElement: ElementRef;
constructor(public maps: GoogleMaps) {
}
ionViewDidLoad() {
this.maps.init(this.mapElement.nativeElement, (latLng) => {
console.log(latLng.lat() + ', ' + latLng.lng());
}).then(() => {
});
}
}

  • Importamos ViewChild y ElementRef para referenciar al div que ubicamos en la vista, donde vamos a cargar el mapa.
  • Importamos nuestro proveedor GoogleMaps.
  • En la línea 9 “hacemos referencia” al elemento div, como mencionamos en el primer punto.
  • Inyectamos en el constructor una instancia del proveedor GoogleMaps y le llamamos maps.
  • Nos suscribimos al evento ionViewDidLoad() el cual se ejecuta cuando la pantalla/página ha sido cargada, inicializamos el mapa utilizando el método init() del nuestro proveedor GoogleMaps el cual recibe el elemento donde vamos a cargar el mapa y el callback que deseamos ejecutar cuando cambiemos la posición (hagamos click) en el mapa, en este caso dicho callback sólo va a imprimir un mensaje en la consola con la latitud y la longitud de la posición seleccionada en el mapa.

Espero que este pequeño tutorial les haya sido útil para el desarrollo de sus aplicaciones. A partir de aquí pueden enriquecer el proveedor GoogleMaps con otros servicios o APIs de Google como Geocoding, Places, etc.

Si te gustó el post ayuda a compartirlo en tus redes sociales 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s