En el siguiente enlace tienes el índice para acceder al resto de entradas de este tutorial:
Indice Tutorial Ionic >>
- Tutorial de Ionic - Construye Apps móviles multiplataforma con ionic desde cero
- Tutorial de Ionic - Instalar ionic y las herramientas necesarias para el desarrollo
- Tutorial de Ionic - Hola Mundo en Ionic
- Tutorial de Ionic - Estructura de un proyecto Ionic
- Tutorial de Ionic - Mini Juego de acertar números en ionic 2, el controlador de la página y Data Binding y *ngIF
- Tutorial de Ionic - Crear una aplicación para guardar nuestros sitios geolocalizados - Parte 1 - Navegación por Tabs
- Tutorial de Ionic - Crear una aplicación para guardar nuestros sitios geolocalizados - Parte 2: Mostrando el mapa.
- Tutorial de Ionic - Crear una aplicación para guardar nuestros sitios geolocalizados - Parte 3: Añadiendo FAB, marcador y ventana modal.
- Tutorial de Ionic - Crear una aplicación para guardar nuestros sitios geolocalizados - Parte 4 - Mostrando la dirección a partir de las coordenadas y sacando foto con la cámara.
- Tutorial de Ionic - Crear una aplicación para guardar nuestros sitios geolocalizados - Parte 5 - Guardando nuestros sitios en una base de datos local
- Tutorial de Ionic - Crear una aplicación para guardar nuestros sitios geolocalizados - Parte 6 - Mostrar detalles del sitio guardado y abrir navegador gps para llegar a el.
- Tutorial de Ionic - Crear una aplicación para guardar nuestros sitios geolocalizados - Parte 7 - Modificar nuestros sitios.
- Tutorial de Ionic - Crear una aplicación para guardar nuestros sitios geolocalizados - Parte 8 - Eliminar un sitio desde el listado deslizando el item con "ItemSliding".
- Tutorial de Ionic - Peticiones http - API REST
- Tutorial de Ionic - Firebase - parte 1: Autenticación con correo y contraseña
- Tutorial de Ionic - Firebase - parte 2: Database - Guardar nuestros sitios en la nube.
- Como mejorar el rendimiento de ionic en iOS y solución al problema de las peticiones http CORS
- Libro: Desarrollo de aplicaciones móviles multiplataforma y PWAs con Ionic y Firebase desde cero.
- Firmar el apk para subirlo a Google Play
- Mostrar un mapa offline en Ionic con Leaflet
- Directiva para mostrar y ocultar menú al hacer scroll en Ionic
- Como crear una app multi idioma con Ionic
- Como crear componentes personalizados con Ionic
Hola a todos:
En el post anterior creamos una aplicación con tres tabs y vimos como navegar entre ellas.
Hoy vamos a seguir construyendo la aplicación.Lo siguiente que vamos a hacer es mostrar un mapa en la página de inicio centrado en las coordenadas actuales donde nos encontremos.
Lo primero que vamos a necesitar es cagar la librería de Google maps , si quieres saber más sobre la api de google maps puedes consultar este tutorial.
Editamos el archivo index.html que es la plantilla principal que se carga al iniciar la aplicación y añadimos la siguiente linea antes de cargar el script build/main.js:
<script src="https://maps.google.com/maps/api/js"></script>
El código completo quedaría así:
<!DOCTYPE html> <html lang="en" dir="ltr"> <head> <meta charset="UTF-8"> <title>Ionic App</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> <meta name="format-detection" content="telephone=no"> <meta name="msapplication-tap-highlight" content="no"> <link rel="icon" type="image/x-icon" href="assets/icon/favicon.ico"> <link rel="manifest" href="manifest.json"> <meta name="theme-color" content="#4e8ef7"> <!-- cordova.js required for cordova apps --> <script src="cordova.js"></script> <!-- un-comment this code to enable service worker if ('serviceWorker' in navigator) { navigator.serviceWorker.register('service-worker.js') .then(() => console.log('service worker installed')) .catch(err => console.log('Error', err)); } --> <link href="build/main.css" rel="stylesheet"> </head> <body> <!-- Ionic's root component and where the app will load --> <ion-app></ion-app> <!-- The polyfills js is generated during the build process --> <script src="build/polyfills.js"></script> <script src="https://maps.google.com/maps/api/js"></script> <!-- The bundle js is generated during the build process --> <script src="build/main.js"></script> </body> </html>
Como vemos esta el la página principal donde se va a cargar todo el contenido de la app dentro de <ion-app></ion-app> que es componente raid de la aplicación.
Ahora para poder acceder a las coordenadas del móvil entra en juego ionic native.
Con ionic native lo que hacemos es instalar un plugin que nos da acceso a alguna característica nativa del móvil como la cámara, el gps, la brújula etc a través de typescript sin tener que programar nosotros en código nativo (Java para Android, Swift o objetive c para iOS).
Simplemente instalamos el plugin y luego importamos el plugin de ionic-native.
En la documentación de ionic podemos ver todos los plugins disponibles en ionic native:
http://ionicframework.com/docs/v2/native/
En esta ocasión necesitamos el plugin cordova-plugin-geolocation.
Este plugin proporciona información sobre la ubicación del dispositivo, tales como la latitud y la longitud.
Para instalarlo desde el terminar dentro de la carpeta de nuestro proyecto tenemos que ejecutar los siguientes comandos:
ionic cordova plugin add cordova-plugin-geolocation --variable GEOLOCATION_USAGE_DESCRIPTION="La app necesita geolocalización" npm install @ionic-native/geolocation --save
Nos sacará un mensaje diciendo que falta instalar el plugin @ionic/cli-plugin-cordova y nos preguntará si queremos instalarlo, le decimos que si.
Si estás utilizando Linux o Mac y te sale un error al intentar instalar el plugin prueba a ejecutar el comando con sudo por delante.
Si os muestra un warning como este:
npm WARN ajv-keywords@2.1.0 requires a peer of ajv@>=5.0.0 but none was installed.
Podeís solucionarlo escribiendo el siguiente comando:
npm install ajv@latest
Antes de nada debemos declarar el plugin como provider en el archivo app.module.ts, para ello editamos dicho archivo, importamos el plugin Geolocation y lo añadimos en la sección providers:
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 { Geolocation } from '@ionic-native/geolocation'; import { MyApp } from './app.component'; @NgModule({ declarations: [ MyApp, ], imports: [ BrowserModule, IonicModule.forRoot(MyApp) ], bootstrap: [IonicApp], entryComponents: [ MyApp, ], providers: [ StatusBar, SplashScreen, {provide: ErrorHandler, useClass: IonicErrorHandler}, Geolocation ] }) export class AppModule {}
Bien, ahora vamos a importar el plugin en el controlador de la página inicio, para ello dentro de la carpeta pages/inicio editamos el archivo inicio.ts e importamos el plugin Geolocation de ionic-native.
También vamos a importar Platform desde ionic-angular para poder acceder al evento ready de Platform que se lanza cuando la aplicación se ha cargado completamente y esta lista. Esto nos evita errores al intentar llamar a un plugin antes de que se haya cargado.
Para importar estos dos módulos incluimos las siguientes lineas en los imports:
import { Geolocation } from '@ionic-native/geolocation';
import { Platform } from 'ionic-angular';
Ahora cuando la aplicación esté completamente cargada y lista (con el evento ready de Platform) vamos a obtener las coordenadas donde nos encontramos y mostrar un mapa centrado en las coordenadas actuales.
Creamos una variable miembro llamada map del tipo any (admite cualquier valor) que contendrá el manejador del mapa de google.
Después para poder utilizar Platform tenemos que inyectarlo como dependencia en el constructor de la clase, también debemos inyectar Geolocation en el constructor. En el evento ready de Platform llamaremos a una función que vamos a llamar obtenerPosicion. En estos momentos el código de inicio.ts debería quedarnos así:
import { Component } from '@angular/core'; import { NavController, NavParams } from 'ionic-angular'; import { Geolocation } from '@ionic-native/geolocation'; import { Platform } from 'ionic-angular'; /* Generated class for the Inicio page. See http://ionicframework.com/docs/v2/components/#navigation for more info on Ionic pages and navigation. */ @IonicPage() @Component({ selector: 'page-inicio', templateUrl: 'inicio.html' }) export class InicioPage { map: any; // Manejador del mapa. constructor( public navCtrl: NavController, public navParams: NavParams, public platform: Platform, private geolocation: Geolocation){ platform.ready().then(() => { // La plataforma esta lista y ya tenemos acceso a los plugins. this.obtenerPosicion(); }); } ionViewDidLoad() { console.log('ionViewDidLoad InicioPage'); } }
Hagamos un pequeño paréntesis en nuestra app para hablar de un par de conceptos que vamos a utilizar con frecuencia en nuestros desarrollos con ionic 2:
Promesas
Vemos que dentro del constructor lamamos al método ready() de platform y después de un punto utilizamos la palabra then(…).
Esto es lo que llamamos una promesa.
Normalmente los plugins de ionic-native nos devuelven una promesa
Las promesas las incluía angular 1 pero ahora las promesas ya son nativas en EMACScript 6.
Las promesas vienen a sustituir a los callbacks. Se ejecuta la función y cuando obtenemos un resultado en el then se ejecuta el código que necesitemos.
Si falla la ejecución de alguno podemos utilizar la función catch para tratar el error.
Funciones de flecha
Otra cosa que te puede resultar rara es que dentro del then en lugar de ejecutar una función al uso estamos utilizando lo que se denomina funciones de flecha o en inglés (Fat Arrow functions).
La funciones con flecha permiten crear funciones anónimas más fácilmente y además permiten utilizar this en el contexto actual.
Vamos a ver un poco más en detalle esto con el siguiente ejemplo:
class MiClase { constructor() { this.nombre = 'Eduardo'; setTimeout(() => { // Esto imprimé en la consola "Eduardo" ya que en las funciones con flecha this hace referencia al contexto actual. console.log(this.nombre); }); } }
Esto sería lo mismo que escribir lo siguiente:
class MiClase { constructor() { this.nombre = 'Eduardo'; var _this = this; setTimeout(function() { console.log(_this.nombre); }); } }
Ahora que ya conocemos lo que son las promesas y las funciones de flecha podemos seguir con nuestra aplicación.
Antes de nada vamos a añadir una variable en en controlador que vamos a vamos a llamar coords y en ella guardaremos un objeto con la latitud y longitud donde nos encontramos.
Por lo tanto encima del constructor de la clase después de la variable map definimos la variable coords:
... export class Inicio { map: any; // Manejador del mapa. coords : any = { lat: 0, lng: 0 } constructor( ...
Si el editor os marca los errores observareis que os subraya this.obtenerPosicion(), esto es evidentemente porque estamos llamando a una función que todavía no hemos definido.
Vamos a definir la función obtenerPosición():
obtenerPosicion():any{ this.geolocation.getCurrentPosition().then(res => { this.coords.lat = res.coords.latitude; this.coords.lng = res.coords.longitude; this.loadMap(); }) .catch( (error)=>{ console.log(error); } ); }
La función getCurrentPosition() del plugin Geolocation nos devuelve una promesa.
Como podemos observar resolvemos la promesa con una función de flecha. En la función de flecha recibimos como parámetro el objeto res. Lo que nos interesa obtener es la longitud y latitud donde nos encontramos, estos valores están en res.coords.longitude y res.coords.latitude.
Asignamos esos valores al objeto de la variable this.cords que acabamos de definir y después llamamos a la función this.loadMap() que aún no hemos creado.
Recordad que debemos de utilizar this para hacer referencia a las variables miembro y métodos que definamos en la clase del controlador.
Ahora deberemos crear la función loadMap que se encargará de mostrar un mapa en la página centrado en las coordenadas que hemos recogido.
Antes de definir la función necesitamos crear el contenedor donde se va a mostrar el mapa en la vista. La librería javascript de Google maps lo que hace es insertar un mapa en un div, por lo que necesitamos crear ese div en la vista y luego pasárselo como referencia para crear el mapa.
Editamos la vista de la página inicio, es decir el archivo inicio.html y añadimos un div dentro de ion-content al que le asignamos como id «map»:
<!-- Generated template for the Inicio page. See http://ionicframework.com/docs/v2/components/#navigation for more info on Ionic pages and navigation. --> <ion-header> <ion-navbar> <ion-title>Inicio</ion-title> </ion-navbar> </ion-header> <ion-content padding> <div id="map"></div> </ion-content>
Ahora tenemos que asignarle un tamaño al mapa así que por primera vez vamos a editar el archivo de estilos de una página, en este caso vamos a editar el archivo inicio.scss.
La extensión del archivo .scss, hace referencia a que es una archivo Sass, sus siglas hacen referencia a (Syntactically Awesome Stylesheets) algo así como «Hoja de estilo sintácticamente impresionante».
Sass es un lenguaje de hoja de estilos que extiende el css tradicional proveyendo de varios mecanismos que están presentes en los lenguaje de programación. Con Sass puedes utilizar variables, código anidado, mixins, etc.
Ionic ya viene con Sass instalado lo que hace realmente fácil su utilización. Sass es un lenguaje de script que es traducido a css. Podemos añadir reglas de estilo de igual manera que lo hacemos con css por lo que de momento para definir el tamaño del mapa no necesitamos saber mas. Si quieres más información sobre Sass puede consultar la documentación oficial: http://sass-lang.com/documentation/
Veamos como tiene que quedar el archivo inicio.scss:
page-inicio { ion-content{ #map { width: 100%; height: 100%; } } }
Como podemos ver dentro del elemento page-inicio definimos el estilo para ion-content y a su vez dentro definimos el estilo para #map al que le estamos diciendo que ocupe todo al ancho y el alto de la página, como vemos Sass nos permite anidar los elementos.
Bien, una vez hechos estos preparativos ya podemos definir la función loadMap que se encargará de mostrar un mapa en la pagina centrado en las coordenadas que hemos recogido. Para que Typescript no de error por no reconocer la clase google cuando la llamemos desde la función que vamos a crear, vamos a declarar la variable google justo debajo de los imports con declare var google: any; . Veamos como tiene que quedar el código de inicio.ts con la variable google definida y nuestra función loadMap:
import { Component } from '@angular/core'; import { NavController, NavParams } from 'ionic-angular'; import { Geolocation } from '@ionic-native/geolocation'; import { Platform } from 'ionic-angular'; declare var google: any; /** * Generated class for the Inicio page. * * See http://ionicframework.com/docs/components/#navigation for more info * on Ionic pages and navigation. */ @IonicPage() @Component({ selector: 'page-inicio', templateUrl: 'inicio.html', }) export class InicioPage { map: any; // Manejador del mapa. coords : any = { lat: 0, lng: 0 } constructor(public navCtrl: NavController, public navParams: NavParams,private geolocation: Geolocation,public platform: Platform) { platform.ready().then(() => { // La plataforma esta lista y ya tenemos acceso a los plugins. this.obtenerPosicion(); }); } ionViewDidLoad() { console.log('ionViewDidLoad Inicio'); } loadMap(){ let mapContainer = document.getElementById('map'); this.map = new google.maps.Map(mapContainer, { center: this.coords, zoom: 12 }); } obtenerPosicion():any{ this.geolocation.getCurrentPosition().then(res => { this.coords.lat = res.coords.latitude; this.coords.lng = res.coords.longitude; this.loadMap(); }) .catch( (error)=>{ console.log(error); } ); } }
En la función loadMap() asignamos a la variable mapContainer el elemento div con id=»map» que habíamos creado en la vista y creamos un mapa con google.maps.Map donde le pasamos dos parámetros, el primero es el elemento contenedor del mapa que lo hemos recogido en la variable mapContainer y el segundo parámetro es un objeto donde le pasamos la configuración del mapa, en este caso le pasamos las coordenadas al parámetro center y le decimos que muestre el mapa con un zoom de 12.
En este punto si probamos nuestra aplicación en el navegador con ionic serve -l deberíamos ver algo como esto:

Para no hacer demasiado largo este post lo vamos a dejar aquí.
En el siguiente post seguiremos desarrollando la app, veremos como añadir un botón FAB, como añadir un marcador al mapa y como crear una ventana modal y pasarle datos desde el controlador de la página que hace la llamada.
Si necesitas desarrollar una aplicación móvil no dudes en solicitarme un presupuesto sin compromiso: