Aitor Sánchez - Blog - Oct. 30, 2023, 10:36 a.m.
¿Pensando en mostrar un mapa en tu aplicación de Ionic con el componente Google Maps Ionic? O quizás ya sabes cómo se hace, pero aún te falta conocer alguna función o campo para dejarlo cómo tú quieres ¿verdad?
Mi nombre es Aitor Sánchez, soy desarrollador de apps desde 2014 y en este artículo aprenderás a mostrar mapas a los usuarios de tus apps mediante el módulo Google Maps Ionic.
Pero antes de continuar, esta es la Flutter Mafia. Es mi newsletter donde aprenderás desarrollo de apps móviles, aso y monetización junto con otros genietes que ya están dentro. Y si te suscribes te regalo mi ebook "Duplica los ingreso de tus apps en 5 minutos" No es broma, quizás te interese.
Ha día de escribir este artículo, 11 de Julio de 2018, hemos probado la integración de la api del Framework en Ionic 3.8 junto con el plugin de cordova necesario para poder acceder a la parte nativa, ordova-plugin-googlemaps (v2.1.0). Hemos comprobado que tiene un rendimiento espectacular junto con Ionic Native 4.
Para todo el que quiera revisar el funcionamiento actual aquí te dejo una demo que nada más que es bajar, instalar paquetes, poner nuestra api key y rular en el móvil la app terminada:
https://github.com/ion-book/demo111
Si aún no tienes esta key tendrás que regístrate en el siguiente link con tu cuenta de google y seguir los pasos necesarios hasta tenerla en nuestras manos:
https://cloud.google.com/maps-platform/?hl=es-419.
Una vez que ya estás registrado tendrás que seleccionar la plataforma para que la vas a usar la api. Y seguir los pasos que se muestran a continuación, es muy sencillo e intuitivo.
Para poder hacer uso de la api tendremos que instalar el plugin de Cordova que nos permite acceder a los componentes nativos e instalar en controlador de Ionic que nos permite comunicarnos sobre la capa intermedia. Para hacerlo vamos a hacer lo siguiente:
ionic cordova plugin add cordova-plugin-googlemaps --variable API_KEY_FOR_ANDROID="YOUR_ANDROID_API_KEY_IS_HERE" --variable API_KEY_FOR_IOS="YOUR_IOS_API_KEY_IS_HERE" --save
npm install @ionic-native/google-maps --save
Nota: Con has visto, el comando que hemos ejecutado nos permite poner la API KEY de Google Maps para Ionic tanto para IOS como para Android. En caso de que lo queramos hacer sin poner la API KEY también lo podremos hacer más adelantes. Simplemente deja lo siguiente:
ionic cordova plugin add cordova-plugin-googlemaps --save
npm install @ionic-native/google-maps --save
El siguiente paso a realizar sería, como hacemos siempre, importar el módulo en nuestro AppModule de la siguiente manera:
...
import { GoogleMaps } from '@ionic-native/google-maps';
...
@NgModule({
declarations: [
MyApp,
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
],
providers: [
StatusBar,
SplashScreen,
GoogleMaps,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
})
export class AppModule {}
Ale, ya podemos hacer uso del componente inyectándolo en los constructores de nuestros componentes.
Muchos sabréis ya como se hace, otros mucho no, pero para estos segundos os dejo un ejemplo:
...
import {
GoogleMaps,
GoogleMap,
GoogleMapsEvent,
GoogleMapOptions,
CameraPosition,
MarkerOptions,
Marker
} from '@ionic-native/google-maps';
@IonicPage()
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(
public navCtrl: NavController,
public geolocation: Geolocation,
) {
...
Como habrás podido ver, en los import, he importado todos los componentes de la api Ionic Maps. Esto no es necesario pero lo he visto oportuno para enseñar cuales son los que podemos utilizar de manera directa.
En los casos finales solo necesitaremos importar lo que vayamos a usar, no importe todo. Más que nada por el principio de Codificación que dicta una buena conducta de codificación importando solo lo necesario en versiones realease.
Una cosa más, aunque quizás no viene demasiado a cuento, también puedes utilizar esta api bajo Angular para la web con ligeras modificaciones. Más adelante, cuando hagamos el curso de Angular, especificaré como lo podemos usar. Pero de momento, si es lo que necesitas, busca por Google que seguro que algo encuentras.
Pues hasta aquí el ejemplo de instalación de la api de Google Maps para Ionic.
Como nuestro caso se trata con ejemplos, que es como mejor se aprende a programar, vamos a escribir dos métodos. “loadMap()” para cargar el mapa y “findPosition()” para recuperar la localización actual de nuestro usuario. ¿Mola no? A mí, la primera vez que lo hice, me encantó. Seguro que a ti también.
loadMap(){
let mapOptions: GoogleMapOptions = {
camera: {
target: {
lat: 43.0741904, // default location
lng: -89.3809802 // default location
},
zoom: 18,
tilt: 30
}
};
this.map = this.googleMaps.create('map_canvas', mapOptions);
// Wait the MAP_READY before using any methods.
this.map.one(GoogleMapsEvent.MAP_READY)
.then(() => {
// Now you can use all methods safely.
this.getPosition();
})
.catch(error =>{
console.log(error);
});
}
Vale, este esta es la función, que como su propio nombre indica, se encarga de cargar el mapa.
Hemos visto, en primer lugar, las opciones con las que queremos que cargue nuestro mapa “GoogleMapsOption”. En este caso vamos a usar las más comunes, pero tiene muchas más que me gustaría que investigaras por tu cuenta.
El campo “camera” inicializa el mapa con los datos que le hemos pasado
Continuamos con el método “create” de nuestro objeto “googleMaps”. Este es el encargado de construir todo el mapa. Como parámetro le pasaremos la estructura de datos que hemos creado anteriormente sobre la clase “GoogleMapsOption”. Esta función devolverá la instancia del mapa sobre la que podemos operar y la vamos a guardar en nuestra variable “map”.
La estructura de control que han aplicado sobre esta api es un patrón de diseño controlado por eventos.
La función “on” controlará los eventos que se generen sobre nuestro map. En el caso del ejemplo hemos controlado el evento “MAP_READY” que es llamado cuando el mapa se ha terminado de construir. Es una promesa que tenemos que controlar desde el “then”, o el “catch” en caso de que falle por alguna razón. Sencillo ¿verdad?
Vale, una vez que se ha llamado a la función de “MAP_READY” vamos a llamar a la segunda función que hemos comentado al principio del punto.
getPosition(): void{
this.map.getMyLocation()
.then(response => {
this.map.moveCamera({
target: response.latLng
});
this.map.addMarker({
title: 'My Position',
icon: 'blue',
animation: 'DROP',
position: response.latLng
});
})
.catch(error =>{
console.log(error);
});
}
Esta función lo que hará, es en esencia, calcular nuestra posición actual, mediante el gps del teléfono, y poner un marcador en el mapa sobre el resultado que le haya ofrecido el sistema.
La función “getMyLocation” es la encargada de recuperar los datos, y como es necesario que sea asíncrona, tenemos que controlarla con un “then” y un “catch” al tratarse de una promesa.
En la respuesta que nos llega vendrán todos estos datos. Pero en los que nos vamos a centrar ahora es en el campo “latLag” que es una clase que, en esencia, nos ahorra tener que controlar las dos variables (latitud y longitud) por separado.
Continuamos hablando de la función “moveCamera”, que como su propio nombre indica, nos permite mover la cámara a los parámetros que le pasamos. En este caso, aunque se puede hacer de otra manera, le tenemos que pasar una interface con el campo “target”. En este “target” pondremos el objeto “latLng” que nos ha llegado a través de la respuesta de la función “getMyLocation” para que la cámara se posicione encima de nuestra posición.
Después agregaremos un marcador con la función “addMarker”. Este rutina recibe como parámetros una interface que consta, aunque tiene más, con los siguientes campos:
El campo más importante, como habrás podido intuir, es el de position. Esta será la posición donde aparezca el marcador, y como en este ejemplo queremos calcular la nuestra, bastará con pasarle el campo “latLng” que nos llega de la respuesta de la función “getMyLocation”, como hemos hecho anteriormente para colocar la cámara.
Genial, pues este sería la manera de usar nuestro componente de Google Maps en TypeScript y su respetiva lógica.
Ahora veamos un poco más lo que tenemos que hacer en el HTML.
Como hemos visto en el ejemplo anterior, cuando hemos llamado al método “create” para construir nuestro mapa, le hemos pasado como primer parámetro un puntero, que hasta el momento, no habíamos visto en ningún sitio.
Pues bien, ese puntero, como podrás imaginar, es el que hace referencia al componente HTML donde queremos que se pinte el mapa.
En este caso hemos usado “map_canvas”, es el que viene por defecto en la documentación, pero podríamos haber usado cualquier otro.
También te puedo decir que el mapa se puede usar en cualquier sitio, y no solo a pantalla completa, este es otro punto bastante interesante de Ionic, dado que en Android nativo esto sería un poco más complicado de hacer. Veamos una HTML donde hacemos uso de nuestro mapa.
<ion-header>
<ion-navbar color="primary">
<ion-title>
Demo 111
</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<div id="map_canvas"></div>
</ion-content>
Este sería el ejemplo de un posible componente normal y corriente, que de hecho si sigues los pasos hasta aquí pintarías un mapa a pantalla completa poniendo una marca sobre tu posición actual.
Pero para ello tendríamos que incluir también el siguiente código CSS:
page-home {
#map_canvas{
display: block;
height: 100%;
width: 100%;
}
}
Visto todo esto ya estás a disposición de usar todo como si fueras un mago, pero lo que no se aún es sí ionic 4 google maps funciona del todo correctamente. Si tienes el tiempo de probarlo te agradecería que lo hicieras y nos lo dejaras en los comentarios como te ha ido.
Una cosa más, si has seguido la guía hasta aquí, que lo probases para ver el resultado. Es flipante y motiva un montón.
ionic cordova run android --prod
He decidido actualizar el artículo para explicar un poco algo que me habéis consultado muchos mediante el correo electrónico. ¿Cómo podemos usar el AutoComplete para los places en G maps. Pues bien, vamos a ver primer el código y luego lo comentamos, como hacemos siempre:
export class HomePage {
public latitude: number;
public longitude: number;
@ViewChild('map') mapElement;
map: any;
marker: any;
search: string;
constructor(public navCtrl: NavController, public platform: Platform) {
/*platform.ready().then(() => {
this.InitMap();
});*/
}
ionViewDidLoad() {
this.InitMap();
}
InitMap() {
this.setLocation();
let input = document.getElementById('places');
let autocomplete = new google.maps.places.Autocomplete(input);
google.maps.event.addListener(autocomplete, 'place_changed', () => {
let place = autocomplete.getPlace();
this.latitude = place.geometry.location.lat();
this.longitude = place.geometry.location.lng();
alert(this.latitude + ", " + this.longitude);
console.log(place);
});
}
setLocation() {
let latLng = new google.maps.LatLng(53.550513, 9.994241);
let mapOptions = {
center: latLng,
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
this.map = new google.maps.Map(this.mapElement.nativeElement, mapOptions);
this.marker = new google.maps.Marker({
position: latLng,
map: this.map,
});
}
}
En primer lugar, y aunque lo veas comentado, en el constructor he metido un comentario haciendo alusión al platformReady de Ionic que se ejecuta en nuestra clase principal. Esto es para que la gente entienda cuando se ha de ejecutar todo el sistema. Si lo ponemos antes, fallará.
Para este fin, y darle un prinper empujón al mapa lo he decidido meter en el ionViewDidLoaded que se ejecutará cuando la vista que hemos vinculado en el componente entre a escena.
El trozo de código que de verdad nos interesa, el resto es ejemplo, es este:
let input = document.getElementById('places');
let autocomplete = new google.maps.places.Autocomplete(input);
google.maps.event.addListener(autocomplete, 'place_changed', () => {
let place = autocomplete.getPlace();
this.latitude = place.geometry.location.lat();
this.longitude = place.geometry.location.lng();
alert(this.latitude + ", " + this.longitude);
console.log(place);
});
Donde el "places" es nuestro input text donde queremos escribir la dirección para que se autocomplete.
Ahora simplemente queda probarlo, y verás lo bien que funciona. Si tienes cualquier problema ya sabes, ponte en contacto conmigo y lo vemos.
Otra de la razones por las que pongo esto aquí, es por que me habéis consultado también como podemos hacer esto por la redes sociales. Aunque esté especificado en la api oficial, cabe lugar a confusión si no entendemos del todo bien como funciona. Vamos a ver un ejemplo:
import {NgZone} from @angular/core
//Inyectamos el ngZone en el constructor
constructor(public navCtrl: NavController,private ngZOne:NgZone) {}
//....
//Pegamos el listener para que ponga un marcador donde hacemos click.
google.maps.event.addListener(marker, 'click', () => {
//Call run function to set the data within angular zone to trigger change detection.
this.ngZone.run(()=>{
this.name = marker.title;
infoWindow.open(this.map, marker)
});
})
Olvidate de todo a excepción de: google.maps.event.addlistener. Esta es la función que nos permitirá pegar un oyente sobre el mapa para poder ejecutar los eventos que nosotros queramos.
Los eventos que tenemos disponibles para ejecutar son los siguientes:
'click'
'dblclick'
'mouseup'
'mousedown'
'mouseover'
'mouseout'
Y para usarlos basta con que hagamos lo siguiente:
marker.addListener('click', function() {
map.setZoom(8);
map.setCenter(marker.getPosition());
});
Super sencillo, ¿verdad? Ahora es hora de que lo pongas en práctica.
El logo de tu aplicación es la puerta de entrada que va a utilizar tu usaurio tanto para entrar a la app, cómo para entrar a su ficha de Google Play. Mejorarlo de manera activa va a aumentar la cantidad de descargas que recibe y los ingresos que te genera. Y por esto mismo, hemos creado esta herramienta para ti, para que puedas evaluar, optimizar y mejorar tus logos. No te espoileo, entra en el enlace.
Sin nada más que agregar, me despido ya. Nos vemos en el siguiente artículo. Hasta entonces, ¡que vaya bien!