Archivo de la categoría: Google Maps

Mostrar un mapa offline en Ionic con Leaflet

Hola a todos:

En posts anteriores vimos como mostrar un mapa de Google maps en ionic, sin embargo ¿que pasa si queremos mostrar información en un mapa sin conexión?, google maps no nos podrá mostrar el mapa.

En lugar de utlizar Google maps en esta ocasión vamos a utilizar Leaflet para mostrar un mapa.

Leaflet  es una biblioteca javascript de código abierto que nos permite crear mapas.

Lanzado por primera vez en 2011, es compatible con la mayoría de las plataformas móviles y de escritorio, y es compatible con HTML5 y CSS3 .

Es una de las bibliotecas de mapas de JavaScript más populares y es utilizada por los sitios web como FourSquare , Pinterest y Flickr .

Para poder mostrar un mapa offline es necesario tener alojados locálmente los titles que forman el mapa, si quieres mostrar un mapa de todo el mundo offline a día de hoy podemos afirmar  que es inviable ya que eso supondría muchísimos gigas de información, sin embargo si que puede ser viable mostrar un mapa offline de una ciudad.

Si por ejemplo estás desarrollando una aplicación de turismo de una ciudad concreta donde vas a mostrar en un mapa  los monumentos que merece la pena visitar en dicha ciudad, o cualquier otra información geolocalizada en un mapa, puede ser interesante el poder mostrar un mapa sin necesidad de tener conexión a Internet en ese preciso momento.

Vamos a ver como podemos solucionar esto en ionic 3, y como siempre la mejor manera de verlo es con un ejemplo.

Lo primero que vamos ha hacer es crear un nuevo proyecto en ionic que vamos a llamar mapaoffline:

ionic start mapaoffline blank

Una vez creado el en proyecto entramos en la carpeta con:

cd mapaoffline

Ahora vamos a descargar Leaflet, para ello descargamos la última versión desde  la sección de descargas de su página oficial en el siguiente enlace:

http://leafletjs.com/download.html

Se habrá descargado un archivo .zip, antes de nada debemos descomprimirlo para extraer su contenido:

 

Ahora vamos a crear una carpeta llamada leaflet en src/assets y dentro vamos a copiar la carpeta images y el archivo leaflet.css.

Una vez hecho esto vamos a cargar el archivo leaflet.css en index.html:

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
  <meta charset="UTF-8">
  <title>Ionic App</title>
  <meta name="viewport" content="viewport-fit=cover, 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">
  
  <!-- add to homescreen for ios -->
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">

  <!-- 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.error('Error', err));
    }
  -->

  <link href="build/main.css" rel="stylesheet">
  <link href="assets/leaflet/leaflet.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>

  <!-- The vendor js is generated during the build process
       It contains all of the dependencies in node_modules -->
  <script src="build/vendor.js"></script>

  
  <!-- The main bundle js is generated during the build process -->
  <script src="build/main.js"></script>

</body>
</html>

Ahora vamos a instalar leaflet desde consola con los siguiente comandos:

npm install leaflet --save
npm install @types/leaflet --save

Ahora que ya tenemos instalado leaflet necesitamos descargar los tiles del mapa que vamos a mostrar, para ello vamos a echar mano de una herramienta llamada Mobile Atlas Creator (MOBAC), para descargarla accedemos al siguiente enlace: http://mobac.sourceforge.net/ y bajamos en la página hasta encontrar Download y pulsamos en latest stable version para descargar la aplicación.

Una vez descargada tenemos que descomprimir el archivo zip y dentro encontraremos el archivo ejecutable.

Al ejecutar Mobile Atlas Creator nos pide introducir un nombre para el atlas (en este caso le llamamos simplemente mapa) y el formato, tenemos que seleccionar Osmdroid ZIP.

 

Pulsamos Aceptar y nos mostrará un mapa, podemos mover zoom para ver mejor la zona que queremos seleccionar. Si hacemos doble click en un punto el mapa hará zoom y se centrará en ese punto, por ello para localizar la zona que queremos mostrar es mejor partir de un zoom que nos permita ver donde estamos e ir haciendo doble click hasta obtener la localización y zoom que nos interesa.

En el panel de la izquierda en la sección map source tenemos los mapas de los que podemos obtener los tiles, muchos son solo de una zona en concreto, yo para este ejemplo voy a utilizar OpenStreetMap4UMaps.eu que nos ofrece un mapa de todo el mundo.

Debajo del panel Map Source tenemos  el panel Zoom Levels, aqui debemos seleccionar los niveles de zoom que queremos que tenga el mapa, cabe mencionar que cuantos más niveles de zoom mas tiles necesitaremos y por ende mas espacio ocuparán las imágenes.

Marcamos por ejemplo 11,12,13,14, y 15.

Ahora tenemos que seleccionar la porción del mapa que queremos descargar:

En la parte de arriba del mapa tenemos una barra de zoom que podemos mover para ver mejor la parte del mapa que queremos seleccionar. Con el ratón sobre el mapa seleccionamos un área.

Yo por ejemplo he seleccionado la zona de Bilbao, de está manera podré mostrar un mapa de Bilbao sin conexión.

Ahora debajo del panel Zoom Levels tenemos el panel Atlas content, aquí vamos a pulsar en el botón Add Selection lo que nos creará un Layer  que si lo desplegamos vemos que contiene dentro los niveles de zoom que hemos seleccionado.

Bien, una vez que hemos seleccionado el área que queremos descargar tenemos que seleccionar Create Atlas y acto seguido comenzará a generar el atlas:

El atlas que se ha generado será un archico .zip con el nombre que le hemos dado al atlas en este caso mapa seguido de la fecha y hora en la que ha sido generado y lo encontrarás en la carpeta atlases dentro de la carpeta  donde tengas Mobile Atlas Creator.

Bien, ahora vamos descomprimir el archivo zip que nos ha generado, al descomprimir vemos que dentro de la carpeta que nos ha creado hay otra carpeta llamada 4uMaps, vamos a cambiarle el nombre a la carpeta por simplemente mapa y a copiar esta carpeta dentro de la carpeta assets de nuestro proyecto:

 

Una vez que tenemos Los tiles copiados en la carpeta assets de nuestro proyecto ya podemos mostrarlos en el mapa.

Vamos a editar home.html e igual que hacíamos cuando creamos un mapa con google maps vamos a crear un div con id=”map” donde se renderizará el mapa:

<ion-header>
<ion-navbar>
  <ion-title>
    Ionic Blank
  </ion-title>
</ion-navbar>
</ion-header>

<ion-content padding>
<div id="map"></div>
</ion-content>

Ahora le vamos a definir el tamaño para que ocupe toda la pantalla por lo tanto editamos home.scss y añadimos lo siguiente:

page-home {
    #map{
        width:100%;
        height: 100%;
    }
}

Ahora en home.ts vamos a ver como se crea un mapa con leaflet:

Lo primero que debemos hacer es importar leaflet:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import * as L from 'leaflet';

Ahora vamos a crear una variable de clase llamada map donde guardaremos la instancia del mapa que vamos a crear:

...

export class HomePage {

  map : any;

  constructor(public navCtrl: NavController) {

  }

...

Ahora cuando se haya cargado la página en el método onViewDidLoad vamos a crear el mapa de la siguiente manera:

ionViewDidLoad() {
  
   this.map = L.map('map').
     setView([ 43.2603479, -2.9334110],
     12);

   L.tileLayer('assets/mapa/{z}/{x}/{y}.png', {    maxZoom: 15  }).addTo(this.map);
   
   L.marker([ 43.2603479,-2.9334110],{draggable: true}).addTo(this.map);
 
 }

Para crear un mapa con Leaflet utilizamos L.map(‘map’), ‘map’ es el id del div que hemos creado en la vista home.html y que es donde se va a renderizar el mapa.

Después con el metodo .setView le indicamos las coordenadas donde se tiene que posicionar el mapa, en este caso son las del centro de Bilbao.

Con L.tileLayer() añadimos al mapa una capa de tiles que va a contener los tiles del mapa que hemos descargado, como primer parámetro le pasamos la ruta donde se encuentran los tiles que puede ser una url si estamos utilizando un mapa online o la ruta donde se encuentrar alojados los archivos para mostrar el mapa offline como es el caso.

Si nos fijamos en la ruta vemos que es ‘assets/mapa/{z}/{x}/{y}.png’,   z, x e y hacen referencia respectivamente al nivel de Zoom, tiles en el eje X y tiles en el eje Y.

Obtendrán el valor correspondiente automáticamente en función de la posición del mapa y al tener la carpeta de los tiles ordenada por estos parámetros no te tienes que preocupar.

Despues con L.marker  creamos un marcador en en las coordenadas indicadas y le decimos que sea  arratrable (draggable) y con .addTo(this.map) lo añadimos a nuestro mapa.

El código completo de home.ts quedaría así:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import * as L from 'leaflet';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  map;

  constructor(public navCtrl: NavController) {

  }

  ionViewDidLoad() {
   
    this.map = L.map('map').
      setView([ 43.2603479, -2.9334110],
      12);

    L.tileLayer('assets/mapa/{z}/{x}/{y}.jpg', {    maxZoom: 15  }).addTo(this.map);
    
    L.marker([ 43.2603479,-2.9334110],{draggable: true}).addTo(this.map);
  
  }

}

Ahora si ejecutamos nuestra app aunque no tengamos conexión a internet podemos mostrar un mapa:

 

Eso es todo por hoy, como siempre espero que os sea de utilidad.

Un saludo, y si aún no lo has hecho no olvides suscribirte a mi blog para no perderte los próximos posts  🙂, también puedes seguirme en Twitter en ‎@revigames y no olvides que me ayudas mucho si compartes este post en las redes sociales.

También os recuerdo que ahora ya puedes comprar mi libro en Amazon actualizado y con contenido extra:

Anuncios

Tutorial de Ionic – Crear una aplicación para guardar nuestros sitios geolocalizados – Parte 3: Añadiendo FAB, marcador y ventana modal.

Hola a todos:

En el post anterior vimos como insertar en nuestra app un mapa de google maps centrado en las coordenadas actuales.
Vamos a continuar desarrollando nuestra app.

Para poder apreciar mejor donde estamos situados vamos a mostrar un marcador personalizado en el mapa que nos indique nuestra posición.

Para el marcador vamos a utilizar una imagen personalizada. La forma correcta de utilizar imágenes locales en nuestra app es alojarlas en la carpeta src/assets, así que vamos a crear dentro de src/assets una carpeta la la que llamaremos img donde alojaremos nuestras imágenes.

Podemos poner la imagen que queramos como  marcador para el mapa. Si no os queréis complicar podéis dar botón derecho sobre la siguiente imagen y descargarla para utilizarla en este ejemplo:

Bien, una vez descargada la imagen la copiamos en la carpeta img que acabamos de crear.

Ahora para situar el marcador en el mapa editamos el archivo inicio.ts y en la función loadMap() que muestra el mapa añadimos el siguiente código:

loadMap(){
 
   let mapContainer = document.getElementById('map');
    this.map = new google.maps.Map(mapContainer, {
      center: this.coords,
      zoom: 12
    });
    
    // Colocamos el marcador
    let miMarker = new google.maps.Marker({
              icon : 'assets/img/ico_estoy_aqui.png',
              map: this.map,
              position: this.coords
          });  

}

No hay mucho que comentar, como veis para crear un marcador creamos un objeto google.maps.Marker  y le pasamos un objeto como parámetro donde en icon le indicamos donde se aloja la imagen del icono, en este caso la ruta a la imagen que hemos guardado destro de assets en la carpeta img es ‘assets/img/ico_estoy_aqui.png’, si vuestra imagen se llama de otra forma tenéis lógicamente que poner el nombre de la imagen que vayáis a utilizar.
En map le idicamos la variable que contiene el mapa donde se tiene que situar, es este caso this.map, por ultimo en position le asignamos las coordenadas donde se tiene que situar, en este caso le pasamos la variable this.coords que contiene las coordenadas actuales.

Ahora si ejecutamos ionic serve -l veremos en el navegador algo como esto:

Mostrando un marcador en el mapa
Mostrando un marcador en el mapa

Ahora vamos a dar un paso más y vamos a añadir un FAB (Floating Action Button) es decir botón de acción flotante al mapa.Los FAB son componentes estándar de material design, tienen la forma de un círculo y flotan sobre el contenido en una posición fija.

Este FAB lo utilizaremos para añadir la posición actual a nuestros sitios, para ello haremos que cuando se pulse en el fav se habra una ventana modal donde mostraremos un pequeño formulario donde aparecerán las coordenadas y la dirección de la posición actual y nos permitirá añadir una descripción y una fotografía desde la cámara de nuestro móvil.

Vayamos por partes.

Primero vamos a colocar el FAB en la vista de muestra página de inicio, editamos el archivo inicio.html y añadimos lo que esta marcado con fondo amarillo.

<!--
  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-fab right top>
    <button ion-fab (tap)="nuevoSitio()">
      <ion-icon name="pin"></ion-icon>
      <ion-icon name="add"></ion-icon>
    </button>
  </ion-fab>
  </ion-content>

Bien, como vemos tenemos el componente ion-fab al que le indicamos que se sitúe arriba a la derecha con right top.

En su interior contiene un botón al que le tenemos que indicar que es del tipo ion-fab.

Con (tap)=”nuevoSitio()” le indicamos que cuando se pulse o tape el botón se llame a la función nuevoSitio() que definiremos luego en el controlador de la página.

Después tenemos dos componentes ion-icon para mostrar los iconos en el FAB, uno con el icono pin y otro con el icono add, lo habitual es mostrar un solo icono, pero he querido poner dos para que quede más claro que queremos añadir una localización.

Si probamos ahora nuestra app tendrá un aspecto similar a este:

Bien, ahora vamos a definir la función nuevoSitio() en el controlador, editamos el archivo inicio.ts y añadimos la siguiente función debajo de la función loadMap:

nuevoSitio(){
 // aquí vamos a abrir el modal para añadir nuestro sitio.
}

La idea es que al llamar a esta función desde el FAB se abra un modal para poder añadir una descripción y una foto a muestro sitio si lo deseamos, vamos a explicar un poco que son los modales y como se utilizan:

Modales

Los modales son como ventanas que se abren dentro de nuestra aplicación sin que afecten a la pila de navegación.

Para crear un modal debemos de crear una página con el ionic generator.
Desde consola vamos a escribir el siguiente comando para crear el modal donde irá el formulario para introducir el nuevo sitio:

ionic g page modalNuevoSitio

Ahora en inicio.ts debemos importar el componente ModalController  de la librería ionic-angular, por lo tanto después de NavController y NavParams importamos también ModalController.

import { NavController, NavParams, ModalController } from 'ionic-angular';

Debemos inyectar también en el constructor el componente ModalController al que hemos llamado modalCtrl:

constructor(
    public navCtrl: NavController, 
    public navParams: NavParams, 
    private geolocation: Geolocation,
    public modalCtrl : ModalController,
    platform: Platform) {  

    ......

Ahora ya estamos listos para crear el modal en nuestra función nuevoSitio.

Para crear un modal utilizamos el método create del componente ModalController y le pasamos como primer parámetro un string con el nombre del  controlador de la página que hemos creado para el modal llamado ModalNuevoSitioPage.
El segundo parámetro es opcional y se utiliza para pasarle datos a nuestro modal, en este caso lo vamos a utilizar para pasarle el objeto this.coords que contiene las coordenadas que hemos obtenido.

Una vez creado el modal para que se muestre en pantalla invocamos al método present();

nuevoSitio(){
  // aquí vamos a abrir el modal para añadir nuestro sitio.
   let mimodal = this.modalCtrl.create( 'ModalNuevoSitioPage',this.coords );
   mimodal.present();
}

Ahora que sabemos como mostrar un modal y como pasarle datos desde la página que lo llama, vamos a ver como recibimos esos datos y los mostramos en el modal.

Recordad que al usar lazy loading y declarar la página del modal en su propio modulo (inicio.module.ts) no debemos declararlo en app.module.ts.

Vamos a crear una variable  en el controlador del modal (modal-nuevo-sitio.ts) que al igual que en la página inicio llamaremos coords y sera de tipo any, esta variable al igual que en la página de inicio va a contener un objeto con la latitud y longitud que recibimos en la llamada.

Para recibir los datos desde la página que llama al modal solo tenemos que utilizar el método get de NavParams que ya se importa por defecto al crear una página. Con navParams controlamos los parámetros que recibimos.
Dentro de la función ionViewDidLoad que se ejecuta al cargar la vista vamos a asignar a cada atributo del objeto coords  que acabamos de crear el valor que corresponde de la latitud y longitud que recibimos.
Veamos como tiene que quedar el código de modal-nuevo-sitio.ts en estos momentos:

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';


/*
  Generated class for the ModalNuevoSitio page.

  See http://ionicframework.com/docs/v2/components/#navigation for more info on
  Ionic pages and navigation.
*/
@IonicPage()
@Component({
  selector: 'page-modal-nuevo-sitio',
  templateUrl: 'modal-nuevo-sitio.html'
})
export class ModalNuevoSitioPage {
  
  coords : any = { lat: 0, lng: 0 }

  constructor(public navCtrl: NavController, public navParams: NavParams) {}

  ionViewDidLoad() {
    console.log('ionViewDidLoad ModalNuevoSitioPage');
    this.coords.lat = this.navParams.get('lat');
    this.coords.lng = this.navParams.get('lng');
  }
}

Ahora que hemos recibido las coordenadas desde la página inicio vamos a mostrarlas en el modal para comprobar que las recibimos correctamente, para ello vamos a editar el archivo modal-nuevo-sitio.html y simplemente añadimos las coordenadas dentro de ion-content:

<ion-content padding>
  <p>Hemos recibido: {{ coords.lat }}, {{ coords.lng }}<p>
</ion-content>

Si probamos ahora muestra aplicación observamos que al pulsar el botón (FAB) que hemos creado para añadir sitios nos abre una ventana modal donde se muestran las coordenadas que acabamos de recibir, pero tenemos un pequeño problema, y es que no tenemos forma de cerrar el modal, así que antes de editar cualquier otra cosa en la página vamos a crear un botón de cerrar.

Para cerrar el modal tenemos que importar en el controlador de la pagina del modal (modal-nuevo-sitio.ts) el controlador ViewController e inyectarlo en el constructor.

Luego creamos una función que vamos a llamar cerrarModal donde utilizaremos  el método dismiss de ViewController para cerrarlo:

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams,  ViewController } from 'ionic-angular';


/*
  Generated class for the ModalNuevoSitio page.

  See http://ionicframework.com/docs/v2/components/#navigation for more info on
  Ionic pages and navigation.
*/
@IonicPage()
@Component({
  selector: 'page-modal-nuevo-sitio',
  templateUrl: 'modal-nuevo-sitio.html'
})
export class ModalNuevoSitioPage {

  coords : any = { lat: 0, lng: 0 }
  constructor(public navCtrl: NavController, public navParams: NavParams, private viewCtrl : ViewController ) {}

  ionViewDidLoad() {
    console.log('ionViewDidLoad ModalNuevoSitioPage');
    this.coords.lat = this.navParams.get('lat');
    this.coords.lng = this.navParams.get('lng');
  }

  cerrarModal(){ 
    this.viewCtrl.dismiss();
  }

}

Ahora vamos a añadir el botón de cerrar que llamará a la función cerrarModal que acabamos de crear  en la cabecera de la vista de la página del modal (modal-nuevo-sitio.html), aprovechamos tambien para cambiar el título del modal a “Nuevo sitio”:

<!--
  Generated template for the ModalNuevoSitio page.

  See http://ionicframework.com/docs/v2/components/#navigation for more info on
  Ionic pages and navigation.
-->
<ion-header>

  <ion-navbar>
    <ion-title>Nuevo sitio</ion-title>
   <ion-buttons start>
      <button ion-button (click)="cerrarModal()">
        <ion-icon name="md-close"></ion-icon>
      </button>
    </ion-buttons>
  </ion-navbar>

</ion-header>

<ion-content padding>
  <p>Hemos recibido: {{ coords.lat }}, {{ coords.lng }}<p>
</ion-content>

Ahora ya tenemos un botón de cerrar para nuestro modal, si habéis seguido correctamente todos los pasos al pulsar sobre el FAV se abrirá nuestro modal como en la siguiente imagen:

Por ahora lo dejamos aquí, hoy hemos aprendido como añadir un marcador al mapa de Google maps, como añadir a nuestra app botones tipo FAB, y como crear, abrir, pasar datos y cerrar un modal.
En el próximo post veremos como añadir un nuevo  con descripción y foto, haciendo uso de la cámara del móvil.

Si aún no lo has hecho no olvides suscribirte a mi blog para no perderte los próximos posts ;). Tambien puedes seguirme en Twitter en ‎@revigames y compartir este post en tus redes sociales.

Un saludo
Ahora ya puedes comprar mi libro en Amazon actualizado y con contenido extra:

Tutorial de Ionic – Crear una aplicación para guardar nuestros sitios geolocalizados – Parte 2: Mostrando el mapa.

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:

Pantalla de Inicio con nuestro mapa
Pantalla de Inicio con nuestro mapa

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.

P.D: si no quieres perderte los próximos posts ¡suscribete a mi blog! también puede seguirme en Twitter en ‎@revigames y si compartes este post en tus redes sociales me haces un favor 😉

¡Un saludo!
Ahora ya puedes comprar mi libro en Amazon actualizado y con contenido extra:

Todo lo que debes saber sobre geolocalización y la api javascript de Google Maps para su uso en tu web o app.

Hola a todos:

He querido realizar un tutorial que recoja todos los elementos que entran en juego a la hora de trabajar con geolocalización en javascript, el uso de la api v3 de google maps y en definitiva todas las posibilidades que nos ofrece la geolocalización a la hora de utilizarla tanto en una web o en una app hibrida que utilice javascript en una webview como  apache cordova/phonegap, ionic, etc.

Como los post muy largos son aburridos de leer he decidido dividir este tutorial en varios capítulos en posts diferentes.

A lo largo de este contenido veremos como mostrar un mapa estático como una imagen, mostrar mapas dinámicos con marcadores, obtener las coordenadas actuales de nuestro dispositivo, obtener las coordenadas de un punto a partir de una dirección, obtener una dirección a partir de unas coordenadas, buscar lugares de interés cercanos al punto donde nos encontramos, aprenderemos a crear una función que calcule la distancia en kilometros entre dos puntos a partir de sus coordenadas. También he añadido un post antiguo donde muestro como abrir el mapa nativo de nuestro dispositivo para mostrar la ruta hasta un punto (Android, iOSm Windows Phone) formando una url concreta en función del sistema operativo que estemos utilizando.

A continuación pos pongo los links a cada uno de los capitulos que forman este tutorial dedicado a la geolocalización:

Al ser un tema extenso es posible que se hayan quedado algunas cosas en el tintero. No dudéis en dejar en los comentarios sugerencias para ampliar este tutorial con algún tema sobre geolocalización en javascript que no se haya tratado, o cualquier comentario que querais hacer al respecto.

Espero que os sea de utilidad.

Un saludo

Javascript – Obtener la distancia distancia en kilómetros entre dos puntos dados por su latitud y longitud.

Como colofón a esta serie de posts sobre la api de google maps, y a pesar de no tener necesariamente que utilizar google maps para utilizar esta función  vamos a crear una función que nos permita conocer la distancia en kilómetros entre dos puntos de un mapa.

Sin mas dilaciones a continuación os muestro la función en cuestión:

/**
 * \fn getKilometros().
 *
 * \Description: Devuelve la distancia en kilomegtros entre dos puntos dados por su latitud y longitud
 *
 * \param (integer) lat1 : Latitud del punto 1
 * \param (integer) long1 : Longitud del punto 1
 * \param (integer) lat2 : Latitud del punto 2
 * \param (integer) long2 : Longitud del punto 2
 *
 * \return (integer) Distancia en kilometros
 *
 **/

 getKilometros = function(lat1,lon1,lat2,lon2)
 {
 rad = function(x) {return x*Math.PI/180;}
var R = 6378.137; //Radio de la tierra en km
 var dLat = rad( lat2 - lat1 );
 var dLong = rad( lon2 - lon1 );
var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(rad(lat1)) * Math.cos(rad(lat2)) * Math.sin(dLong/2) * Math.sin(dLong/2);
 var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
 var d = R * c;
return d.toFixed(3); //Retorna tres decimales
 }

Para utilizar esta función solo tenemos llamarla pasando como parámetros la latitud del primer punto, la longitud del primer punto, la latitud del segundo punto y la longitud del segundo punto.

Esta función puede ser muy útil por ejemplo si tenemos varios puntos con sus coordenadas  que extraemos de una base de datos propia y queremos filtrar solo los que se encuentren a cierta distancia del punto que nos interesa, por ejemplo, los que se encuentren a 5 kilómetros a la redonda  de las coordenadas actuales.En este caso podríamos recorrer un array con todos los puntos y preguntar por los que se encuentran a menos de 5 kilómetros de la siguiente manera:

Imaginemos que tenemos un array A con varios puntos y sus coordenadas y queremos meter en el array B los puntos que se encuentran a menos de 5 kilómetros de las coordenadas actuales, podríamos hacer algo como esto:

navigator.geolocation.getCurrentPosition(function(pos) { 
 var lat = pos.coords.latitude;
 var lon = pos.coords.longitude;
 for (var i=0; i<A.length; i++)
 {
   if(parseInt(getKilometros(lat,lon,A[i].laitude,A[i].lon))<= 5
   {
     B.push(A[i]);
   }
 }
}

 

Esto es todo por ahora, espero que os haya servido de ayuda.

No dudéis en dejar en los comentarios cualquier sugerencia.

Un saludo

Índice   –   <– Capítulo Anterior   –  Capitulo Siguiente –>

Api javascript de Google Maps – Buscar lugares cercanos

En este apartado del tutorial sobre la Api javascript v3 de Google Maps vamos a ver como podemos buscar lugares cercanos de interés.

Por ejemplo podemos buscar las cafeterías,farmacias, etc que se encuentren cercanas al lugar donde nos encontramos. Para ello usaremos el servicio de búsqueda de Google Maps.

Lo primero que tenemos que tener en cuenta es que cuando añadamos el javascript de google maps tenemos que indicarle en la url que vamos a utilizar la librería places de la siguiente manera:

< script type="text/javascript" src="https://maps.google.com/maps/api/js?libraries=places"></script>

Una vez más vamos a mostrar con un ejemplo como funciona.
Vamos a crear un mapa centrado en las coordenadas actuales y en el mostraremos marcadores con las cafeterías que se encuentren en un radio de 5000 metros alrededor del punto donde nos encontramos. Al pinchar sobre un marcador se abrirá un infowíndow con el nombre de la cafetería.

<!DOCTYPE html>
<html lang="es">
<head>
<title>Obtener lugares cercanos</title>
<meta charset="utf-8" />
< script type="text/javascript" src="https://maps.google.com/maps/api/js?libraries=places"></script>
< script> 
 var map;
 var infowindow;

 function initMap()
 {
 // Creamos un mapa con las coordenadas actuales
   navigator.geolocation.getCurrentPosition(function(pos) {
 
   lat = pos.coords.latitude;
   lon = pos.coords.longitude;
 
   var myLatlng = new google.maps.LatLng(lat, lon);
 
   var mapOptions = {
     center: myLatlng,
     zoom: 14,
     mapTypeId: google.maps.MapTypeId.SATELLITE
   };
 
   map = new google.maps.Map(document.getElementById("mapa"),  mapOptions);
 
   // Creamos el infowindow
   infowindow = new google.maps.InfoWindow();
 
   // Especificamos la localización, el radio y el tipo de lugares que queremos obtener
   var request = {
     location: myLatlng,
     radius: 5000,
     types: ['cafe']
   };
 
   // Creamos el servicio PlaceService y enviamos la petición.
   var service = new google.maps.places.PlacesService(map);
 
   service.nearbySearch(request, function(results, status) {
     if (status === google.maps.places.PlacesServiceStatus.OK) {
       for (var i = 0; i < results.length; i++) {
         crearMarcador(results[i]);
       }
     }
   });
 }); 
}
 
 function crearMarcador(place)
 {
   // Creamos un marcador
   var marker = new google.maps.Marker({
     map: map,
     position: place.geometry.location
   });
 
 // Asignamos el evento click del marcador
   google.maps.event.addListener(marker, 'click', function() {
     infowindow.setContent(place.name);
     infowindow.open(map, this);
   });
   }
</script>
</head>
<body onload="initMap()">
 <h1>obtener lugares cercanos</h1>
 < div id="mapa" style="width: 450px; height: 350px;"> </div>
</body>
</html>

Analicemos el código:

En el evento onload del body llamamos a la función initMap. En esta función recogemos lar coordenadas actuales con navigator.geolocation.getCurrentPosition tal y como vimos en los posts anteriores.

Con las coordenadas obtenidas generamos el mapa centrado en la posición donde nos encontramos.

Creamos  también un infowindow, que es una especie de “bocadillo” que se muestra en el mapa. Lo utilizaremos para mostrar el nombre de la cafetería correspondiente cuando pinchemos sobre un marcador.

Después creamos el objeto resquest con los parámetros de la búsqueda:

En location indicamos las coordenadas donde va a buscar, en este caso le pasamos las actuales que hemos almacenado en la variable myLatlng.

En radius indicamos el radio en metros a partir de nuestra posición en la que se va a buscar, en este caso le hemos indicado 5000 metros.

Por último en types le pasamos un array con los tipos de búsqueda que queremos hacer, en este caso ‘cafe’.

Puedes usar los siguientes valores en el filtro types para las búsquedas de sitios:

  • accounting                                        – Contabilidad
  • airport                                                – Aeropuerto
  • amusement_park                          – Parque de atracciones
  • aquarium                                          – Acuario
  • art_gallery                                        – Galería de arte
  • atm                                                      – Cajero automático
  • bakery                                                – Panadería
  • bank                                                    – Banco
  • bar                                                        – Bar
  • beauty_salon                                  – Salón de belleza
  • bicycle_store                                   – Tienda de bicicletas
  • book_store                                       – Librería
  • bowling_alley                                  – Bolera
  • bus_station                                      – Estación de autobuses
  • cafe                                                       – Cafetería
  • campground                                     – Camping
  • car_dealer                                         – Concesionario de coches
  • car_rental                                          – Alquiler de coches
  • car_repair                                          – Reparación de coches
  • car_wash                                           – Lavado de coches
  • casino                                                 – Casino
  • cemetery                                           – Cementerio
  • church                                                – Iglesia
  • city_hall                                            – Ayuntamiento
  • clothing_store                                – Tienda de ropa
  • convenience_store                       – Supermercado
  • courthouse                                      – Juzgado
  • dentist                                               – Dentista
  • department_store                        – Grandes almacenes
  • doctor                                                – Médico
  • electrician                                        – Electricista
  • electronics_store                          – Tienda de electrónica
  • embassy                                            – Embajada
  • establishment                                – Establecimiento
  • finance                                              – Finanzas
  • fire_station                                      – Estación de bomberos
  • florist                                                 – Florista
  • food                                                    – Comida
  • funeral_home                                – Funeraria
  • furniture_store                              – Tienda de muebles
  • gas_station                                     – Gasolinera
  • general_contractor                      – Contratista
  • grocery_or_supermarket          – Tienda de comestibles o supermercado
  • gym                                                    – Gimnasio
  • hair_care                                          – Cuidado del cabello
  • hardware_store                             – Ferretería
  • health                                                – Salud
  • hindu_temple                                – Templo hindú
  • home_goods_store                     – Tienda de artículos para el hogar
  • hospital                                            – Hospital
  • insurance_agency                       – Agencia de seguros
  • jewelry_store                                 – Joyería
  • laundry                                            –  Lavandería
  • lawyer                                              –  Abogado
  • library                                              – Biblioteca
  • liquor_store                                   – Tienda de licores
  • local_government_office        – Oficina del gobierno local
  • locksmith                                       – Cerrajero
  • lodging                                            – Alojamiento
  • meal_delivery                              – Entrega de comidas
  • meal_takeaway                           – Comida para llevar
  • mosque                                          – Mezquita
  • movie_rental                                – Alquiler de películas
  • movie_theater                             – Cine
  • moving_company                      – Empresa de mudanzas
  • museum                                         – Museo
  • night_club                                     – Club nocturno
  • painter                                            – Pintor
  • park                                                 – Parque
  • parking                                           – Aparcamiento
  • pet_store                                       – Tienda de mascotas
  • pharmacy                                      – Farmacia
  • physiotherapist                          – Fisioterapeuta
  • place_of_worship                      – Lugar de adoración
  • police                                              – Policía
  • post_office                                   – Oficina de correo
  • real_estate_agency                  – Agencia inmobiliaria
  • restaurant                                     – Restaurante
  • roofing_contractor                   – Contratista de tejados
  • rv_park                                          – Parque de caravanas
  • school                                            – Colegio
  • shoe_store                                   – Zapatería
  • shopping_mall                           – Centro comercial
  • spa                                                   – Spa
  • stadium                                         – Estadio
  • storage                                           – Almacenaje
  • store                                                – Tienda
  • subway_station                          – Estación de metro
  • synagogue                                    – Sinagoga
  • taxi_stand                                    – Parada de taxi
  • train_station                               – Estación de tren
  • travel_agency                             – Agencia de viajes
  • university                                      – Universidad
  • veterinary_care                          – Veterinario
  • zoo                                                   – Zoo

Después  creamos el servicio PlaceService:

var service = new google.maps.places.PlacesService(map);

Y enviamos la petición con service.nearbySearch() pasandole como primer parámetro las opciones de busqueda de la variable request y como segundo una función callback donde recibiremos los resultados de la búsqueda.

Dentro de esta función recorremos los resultados obtenidos que los recibimos en el parámetro results y  llamamos a la funcion crearMarcador().

En la función crear marcador creamos un nuevo marcador por cada lugar de la búsqueda y le decimos que en el evento click asigne al infowindow que teníamos creado  el contenido con el nombre del lugar, en este caso de la cafetería, y acto seguido abra el infowindow mostrando dicha información.

Los datos de un lugar que podemos recibir en una búsqueda son:

  • geometry
  • icon
  • id
  • name
  • place_id
  • reference
  • scope
  • types
  • vicinity
  • html_attributions

Si el lugar tiene fotos asignadas también podemos obtener la url de la foto indicandole el tamaño que queramos con la función getUrl. En el siguiente ejemplo sacamos un alert con la url de la primera foto (en caso de tener) con un tamaño 350×350:

 if(place.photos)
 {
 alert(place.photos[0].getUrl({'maxWidth': 350, 'maxHeight': 350}));
 }

Si necesitamos obtener información extra sobre un lugar podemos utilizar service.getDetails()  pasandole como parámetros un objeto con el id del lugar que hemos recibido de la búsqueda y como segundo parámetro una función donde recibimos la información extra sobre un punto. Por ejemplo teniendo el id del lugar que lo tenemos en la propiedad place_id de cada lugar recibido en la búsqueda podemos hacer una llamada a service.getDetails de la siguiente manera:

var service = new google.maps.places.PlacesService(map);
service.getDetails({
   placeId: place.place_id
 }, function (placeDetails, status) {
 if (status == google.maps.places.PlacesServiceStatus.OK) {
   alert('placeDetails.formatted_address');
 });

Los datos que podemos extraer de un sitio con getDetails son:

  • address_components
  • adr_address
  • formatted_address
  • formatted_phone_number
  • geometry
  • icon
  • id
  • international_phone_number
  • name
  • place_id
  • reference
  • scope
  • types
  • url
  • utc_offset
  • vicinity
  • html_attributions

Como ejercicio puede ser interesante sacar un alert de cada dato recivido para ver que contiene y que información puede sernos útiles para nuestro propósito.

Para saber mas sobre Places library puedes visitar la documentación de google en https://developers.google.com/maps/documentation/javascript/places

Índice   –   <– Capítulo Anterior   –  Capitulo Siguiente –>

Obtener Coordenadas a partir de una dirección

En el anterior post vimos como obtener una dirección a partir de unas coordenadas, en esta ocasión vamos a realizar el proceso contrario.

Vamos a obtener unas coordenadas a partir de una dirección en formato texto.

Una vez más vamos a crear un ejemplo para ilustrar mejor como funciona y las posibilidades que ofrece.

En el ejemplo que os propongo vamos a mostrar un mapa y una caja de texto donde introduciremos la dirección que deseamos buscar, al pulsar e el botón el mapa se centrará en esa dirección mostrando en ella el marcador.

veamos el código que necesitamos para conseguir esto:

<!DOCTYPE html>
<html lang="es">
<head>
<title>Obtener Coordenadas a partir de una dirección</title>
<meta charset="utf-8" />
<script type="text/javascript" src="https://maps.google.com/maps/api/js"></script>
<script>

mapa = {
 map : false, 
 marker : false,

 initMap : function() {
 
 // Creamos un objeto mapa y especificamos el elemento DOM donde se va a mostrar.
 
 mapa.map = new google.maps.Map(document.getElementById('mapa'), {
   center: {lat: 43.2686751, lng: -2.9340005},
   scrollwheel: false,
   zoom: 14,
   zoomControl: true,
   rotateControl : false,
   mapTypeControl: true,
   streetViewControl: false,
 });
 
 // Creamos el marcador
 mapa.marker = new google.maps.Marker({
 position: {lat: 43.2686751, lng: -2.9340005},
 draggable: true 
 });
 
 // Le asignamos el mapa a los marcadores.
  mapa.marker.setMap(mapa.map);
 
 },

// función que se ejecuta al pulsar el botón buscar dirección
getCoords : function()
{
  // Creamos el objeto geodecoder
 var geocoder = new google.maps.Geocoder();
 
 address = document.getElementById('search').value;
 if(address!='')
 {
  // Llamamos a la función geodecode pasandole la dirección que hemos introducido en la caja de texto.
 geocoder.geocode({ 'address': address}, function(results, status)  
 {
   if (status == 'OK')
   {
// Mostramos las coordenadas obtenidas en el p con id coordenadas
   document.getElementById("coordenadas").innerHTML='Coordenadas:   '+results[0].geometry.location.lat()+', '+results[0].geometry.location.lng();
// Posicionamos el marcador en las coordenadas obtenidas
   mapa.marker.setPosition(results[0].geometry.location);
// Centramos el mapa en las coordenadas obtenidas
   mapa.map.setCenter(mapa.marker.getPosition());
   agendaForm.showMapaEventForm();
   }
  });
 }
 }
}
</script>
</head>
<body onload="mapa.initMap()">
 <h1>Obtener Coordenadas a partir de una dirección</h1>
 <div id="mapa" style="width: 450px; height: 350px;"> </div>
 <div><p id="coordenadas"></p></div>
 <input type="text" id="search"> <input type="button" value="Buscar Dirección" onClick="mapa.getCoords()">
</body>
</html>

Como Podemos observar el proceso es muy parecido al mostrado en la entrada Obtener la dirección a partir de unas coordenadas con la diferencia de que en esta ocasión le pasamos a geodecoder como parámetro la dirección en lugar de las coordenadas, y en la función callback que le pasamos recibimos las coordenadas en results[0].geometry.location.

Como necesitamos tener acceso a la variable map, y a la variable marker desde la función getCoords y no es buena practica crear variables globales, hemos creado un objeto llamado mapa para proteger el espacio de nombres y dentro hemos definido las dos variables y las dos funciones. Como ya sabemos initMap se llama en el evento onload del body, y getCoords al pulsar el botón de buscar,  como están dentro del objeto mapa tenemos que añadirles mapa. por delante para ejecutarlas.

Con este sencillo código obtenemos un potente buscador utilizando la api de google maps.

Índice   –   <– Capítulo Anterior   –  Capitulo Siguiente –>