Cómo construir una aplicación de geocodificación en Vue.js usando Mapbox

Publicado: 2022-03-10
Resumen rápido ↬ En esta guía, daremos un vistazo general a los conceptos de geocodificación directa y geocodificación inversa. Crearemos una miniaplicación que aplique estos conceptos para mostrar ubicaciones específicas, utilizando Mapbox y Vue.js 2.6.11 para lograrlo.

La precisión milimétrica y la modularidad se encuentran entre las ventajas que hacen que los códigos geográficos sean el medio perfecto para encontrar una ubicación en particular.

En esta guía, crearemos una aplicación de geocodificación simple desde cero, utilizando Vue.js y Mapbox. Cubriremos el proceso desde la construcción del andamiaje frontal hasta la construcción de un geocodificador para manejar la geocodificación directa y la geocodificación inversa. Para aprovechar al máximo esta guía, necesitará una comprensión básica de JavaScript y Vue.js y cómo realizar llamadas API.

¿Qué es la geocodificación?

La geocodificación es la transformación de ubicaciones basadas en texto en coordenadas geográficas (normalmente, longitud y latitud) que indican una ubicación en el mundo.

La geocodificación es de dos tipos: directa e inversa . La geocodificación directa convierte los textos de ubicación en coordenadas geográficas, mientras que la geocodificación inversa convierte las coordenadas en textos de ubicación.

En otras palabras, la geocodificación inversa convierte 40.714224, -73.961452 en "277 Bedford Ave, Brooklyn", y la geocodificación directa hace lo contrario, convirtiendo "277 Bedford Ave, Brooklyn" en 40.714224, -73.961452.

Para brindar más información, crearemos una mini aplicación web que utiliza un mapa web interactivo con marcadores personalizados para mostrar las coordenadas de ubicación, que luego decodificaremos en textos de ubicación.

Nuestra app contará con las siguientes funciones básicas:

  • dar acceso al usuario a una pantalla de mapa interactivo con un marcador;
  • permitir al usuario mover el marcador a voluntad, mientras muestra las coordenadas;
  • devolver una ubicación basada en texto o coordenadas de ubicación a pedido del usuario.
¡Más después del salto! Continúe leyendo a continuación ↓

Configurar proyecto usando Vue CLI

Haremos uso de la plantilla que se encuentra en este repositorio. Contiene un nuevo proyecto con Vue CLI e yarn como administrador de paquetes. Deberá clonar el repositorio. Asegúrese de estar trabajando desde la rama geocoder/boilerplate .

Configurar la estructura de archivos de la aplicación

A continuación, necesitaremos configurar la estructura de archivos de nuestro proyecto. Cambie el nombre del archivo Helloworld.vue en la carpeta del componente a Index.vue y déjelo en blanco por ahora. Continúe y copie lo siguiente en el archivo App.vue :

 <template> <div> <!--Navbar Here --> <div> <nav> <div class="header"> <h3>Geocoder</h3> </div> </nav> </div> <!--Index Page Here --> <index /> </div> </template> <script> import index from "./components/index.vue"; export default { name: "App", components: { index, }, }; </script>

Aquí, importamos y luego registramos localmente el componente recientemente renombrado. También hemos agregado una barra de navegación para mejorar la estética de nuestra aplicación.

Necesitamos un archivo .env para cargar las variables de entorno. Continúe y agregue uno en la raíz de la carpeta de su proyecto.

Instalar paquetes y bibliotecas requeridos

Para iniciar el proceso de desarrollo, necesitaremos instalar las bibliotecas necesarias. Aquí hay una lista de los que usaremos para este proyecto:

  1. Mapbox GL JS
    Esta biblioteca de JavaScript utiliza WebGL para representar mapas interactivos a partir de mosaicos vectoriales y Mapbox.
  2. Mapbox-gl-geocodificador
    Este control de geocodificador para Mapbox GL ayudará con nuestra geocodificación directa.
  3. Dotenv
    No tendremos que instalar esto porque viene preinstalado con Vue CLI. Nos ayuda a cargar variables de entorno desde un archivo .env en process.env . De esta manera, podemos mantener nuestras configuraciones separadas de nuestro código.
  4. Axios
    Esta biblioteca nos ayudará a realizar solicitudes HTTP.

Instale los paquetes en su CLI de acuerdo con su administrador de paquetes preferido. Si está utilizando Yarn, ejecute el siguiente comando:

 cd geocoder && yarn add mapbox-gl @mapbox/mapbox-gl-geocoder axios

Si está utilizando npm, ejecute esto:

 cd geocoder && npm i mapbox-gl @mapbox/mapbox-gl-geocoder axios --save

Primero tuvimos que ingresar a la carpeta del geocoder antes de ejecutar el comando de instalación.

Andamiaje del front-end con Vue.js

Avancemos y creemos un diseño para nuestra aplicación. Necesitaremos un elemento para albergar nuestro mapa, una región para mostrar las coordenadas mientras escuchamos el movimiento del marcador en el mapa y algo para mostrar la ubicación cuando llamamos a la API de geocodificación inversa. Podemos albergar todo esto dentro de un componente de tarjeta.

Copie lo siguiente en su archivo Index.vue :

 <template> <div class="main"> <div class="flex"> <!-- Map Display here --> <div class="map-holder"> <div></div> </div> <!-- Coordinates Display here --> <div class="dislpay-arena"> <div class="coordinates-header"> <h3>Current Coordinates</h3> <p>Latitude:</p> <p>Longitude:</p> </div> <div class="coordinates-header"> <h3>Current Location</h3> <div class="form-group"> <input type="text" class="location-control" :value="location" readonly /> <button type="button" class="copy-btn">Copy</button> </div> <button type="button" class="location-btn">Get Location</button> </div> </div> </div> </div> </template>

Para ver lo que tenemos actualmente, inicie su servidor de desarrollo. Para hilo:

 yarn serve

O para npm:

 npm run serve

Nuestra aplicación debería verse así ahora:

Vista previa del andamio
Vista previa del andamio de la aplicación de geocodificación. (Vista previa grande)

El punto en blanco a la izquierda se ve apagado. Debería albergar nuestra pantalla de mapa. Agreguemos eso.

Visualización de mapas interactivos con Mapbox

Lo primero que debemos hacer es obtener acceso a las bibliotecas Mapbox GL y Geocoder. Comenzaremos importando las bibliotecas Mapbox GL y Geocoder en el archivo Index.vue .

 import axios from "axios"; import mapboxgl from "mapbox-gl"; import MapboxGeocoder from "@mapbox/mapbox-gl-geocoder"; import "@mapbox/mapbox-gl-geocoder/dist/mapbox-gl-geocoder.css";

Mapbox requiere un token de acceso único para calcular mosaicos de vectores de mapas. Obtenga el suyo y agréguelo como una variable ambiental en su archivo .env .

 .env
 VUE_APP_MAP_ACCESS_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

También necesitamos definir propiedades que ayudarán a juntar los mosaicos de nuestro mapa en nuestra instancia de datos. Agregue lo siguiente debajo del lugar donde importamos las bibliotecas:

 export default { data() { return { loading: false, location: "", access_token: process.env.VUE_APP_MAP_ACCESS_TOKEN, center: [0, 0], map: {}, }; }, }
  • La propiedad de location se modelará según la entrada que tengamos en nuestro andamiaje. Usaremos esto para manejar la geocodificación inversa (es decir, mostrar una ubicación a partir de las coordenadas).
  • La propiedad center alberga nuestras coordenadas (longitud y latitud). Esto es fundamental para armar los mosaicos de nuestro mapa, como veremos en breve.
  • La propiedad access_token se refiere a nuestra variable ambiental, que agregamos anteriormente.
  • La propiedad del map sirve como constructor para nuestro componente de mapa.

Procedamos a crear un método que trace nuestro mapa interactivo con nuestro geocodificador directo incrustado en él. Este método es nuestra función base, sirviendo como intermediario entre nuestro componente y Mapbox GL; llamaremos a este método createMap . Agregue esto debajo del objeto de datos:

 mounted() { this.createMap() }, methods: { async createMap() { try { mapboxgl.accessToken = this.access_token; this.map = new mapboxgl.Map({ container: "map", style: "mapbox://styles/mapbox/streets-v11", center: this.center, zoom: 11, }); } catch (err) { console.log("map error", err); } }, },

Para crear nuestro mapa, especificamos un container que alberga el mapa, una propiedad de style para el formato de visualización de nuestro mapa y una propiedad center para albergar nuestras coordenadas. La propiedad center es un tipo de matriz y contiene la longitud y la latitud.

Mapbox GL JS inicializa nuestro mapa en función de estos parámetros en la página y nos devuelve un objeto Map . El objeto Map se refiere al mapa en nuestra página, al tiempo que expone métodos y propiedades que nos permiten interactuar con el mapa. Hemos almacenado este objeto devuelto en nuestra instancia de datos, this.map .

Reenviar geocodificación con Mapbox Geocoder

Ahora, agregaremos el geocodificador y el marcador personalizado. El geocodificador maneja la geocodificación directa transformando ubicaciones basadas en texto en coordenadas. Esto aparecerá en forma de un cuadro de entrada de búsqueda adjunto a nuestro mapa.

Agregue lo siguiente debajo de la inicialización de this.map que tenemos arriba:

 let geocoder = new MapboxGeocoder({ accessToken: this.access_token, mapboxgl: mapboxgl, marker: false, }); this.map.addControl(geocoder); geocoder.on("result", (e) => { const marker = new mapboxgl.Marker({ draggable: true, color: "#D80739", }) .setLngLat(e.result.center) .addTo(this.map); this.center = e.result.center; marker.on("dragend", (e) => { this.center = Object.values(e.target.getLngLat()); }); });

Aquí, primero creamos una nueva instancia de un geocodificador utilizando el constructor MapboxGeocoder . Esto inicializa un geocodificador basado en los parámetros proporcionados y devuelve un objeto, expuesto a métodos y eventos. La propiedad accessToken se refiere a nuestro token de acceso a Mapbox, y mapboxgl se refiere a la biblioteca de mapas utilizada actualmente.

El núcleo de nuestra aplicación es el marcador personalizado; el geocodificador viene con uno por defecto. Sin embargo, esto no nos daría toda la personalización que necesitamos; por lo tanto, lo hemos deshabilitado.

Avanzando, hemos pasado nuestro geocodificador recién creado como un parámetro al método addControl , expuesto a nosotros por nuestro objeto de mapa. addControl acepta un control como parámetro.

Para crear nuestro marcador personalizado, hemos hecho uso de un evento expuesto por nuestro objeto geocodificador. El detector on eventos nos permite suscribirnos a los eventos que suceden dentro del geocodificador. Acepta varios eventos como parámetros. Estamos escuchando el evento de result , que se activa cuando se establece una entrada.

En pocas palabras, en result , nuestro constructor de marcadores crea un marcador, en función de los parámetros que hemos proporcionado (un atributo y un color que se pueden arrastrar, en este caso). Devuelve un objeto, con el que usamos el método setLngLat para obtener nuestras coordenadas. Agregamos el marcador personalizado a nuestro mapa existente usando el método addTo . Finalmente, actualizamos la propiedad del center en nuestra instancia con las nuevas coordenadas.

También tenemos que seguir el movimiento de nuestro marcador personalizado. Logramos esto usando el detector de eventos dragend y actualizamos nuestra propiedad center con las coordenadas actuales.

Actualicemos la plantilla para mostrar nuestro mapa interactivo y geocodificador de reenvío. Actualice la sección de visualización de coordenadas en nuestra plantilla con lo siguiente:

 <div class="coordinates-header"> <h3>Current Coordinates</h3> <p>Latitude: {{ center[0] }}</p> <p>Longitude: {{ center[1] }}</p> </div>

¿Recuerdas que siempre actualizamos la propiedad de nuestro center después de un evento? Estamos mostrando las coordenadas aquí basadas en el valor actual.

Para realzar la estética de nuestra aplicación, agregue el siguiente archivo CSS en la sección head del archivo index.html . Coloque este archivo en la carpeta pública.

 <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.53.0/mapbox-gl.css" rel="stylesheet" />

Nuestra aplicación debería verse así ahora:

Reenviar vista previa de geocodificación
Reenviar vista previa de geocodificación. (Vista previa grande)

Ubicación de geocodificación inversa con Mapbox API

Ahora, manejaremos la geocodificación inversa de nuestras coordenadas a ubicaciones basadas en texto. Escribamos un método que maneje eso y lo activemos con el botón Get Location en nuestra plantilla.

La geocodificación inversa en Mapbox es manejada por la API de geocodificación inversa. Esto acepta longitude , latitude y access token como parámetros de solicitud. Esta llamada devuelve una carga útil de respuesta, por lo general, con varios detalles. Nuestra preocupación es el primer objeto en la matriz de features , donde está la ubicación geocodificada inversa.

Tendremos que crear una función que envíe la longitude , la latitude y access_token de la ubicación a la que queremos llegar a la API de Mapbox. Necesitamos enviarlos para obtener los detalles de esa ubicación.

Finalmente, necesitamos actualizar la propiedad de location en nuestra instancia con el valor de la clave place_name en el objeto.

Debajo de la función createMap() , agreguemos una nueva función que maneje lo que queremos. Así es como debería verse:

 async getLocation() { try { this.loading = true; const response = await axios.get( `https://api.mapbox.com/geocoding/v5/mapbox.places/${this.center[0]},${this.center[1]}.json?access_token=${this.access_token}` ); this.loading = false; this.location = response.data.features[0].place_name; } catch (err) { this.loading = false; console.log(err); } },

Esta función realiza una solicitud GET a la API de Mapbox. La respuesta contiene place_name : el nombre de la ubicación seleccionada. Obtenemos esto de la respuesta y luego lo establecemos como el valor de this.location .

Con eso hecho, necesitamos editar y configurar el botón que llamará a esta función que hemos creado. Haremos uso de un detector de eventos de click , que llamará al método getLocation cuando un usuario haga clic en él. Continúe y edite el componente del botón a esto.

 <button type="button" :disabled="loading" :class="{ disabled: loading }" class="location-btn" @click="getLocation" > Get Location </button>

Como guinda del pastel, adjuntemos una función para copiar la ubicación mostrada en el portapapeles. Agregue esto justo debajo de la función getLocation :

 copyLocation() { if (this.location) { navigator.clipboard.writeText(this.location); alert("Location Copied") } return; },

Actualice el componente del botón Copy para activar esto:

 <button type="button" class="copy-btn" @click="copyLocation">

Conclusión

En esta guía, hemos analizado la geocodificación con Mapbox. Creamos una aplicación de geocodificación que transforma ubicaciones basadas en texto en coordenadas, mostrando la ubicación en un mapa interactivo y que convierte coordenadas en ubicaciones basadas en texto, de acuerdo con la solicitud del usuario. Esta guía es solo el comienzo. Se podría lograr mucho más con las API de codificación geográfica, como cambiar la presentación del mapa utilizando los diversos estilos de mapa proporcionados por Mapbox.

  • El código fuente está disponible en GitHub.

Recursos

  • “Geocodificación”, documentación de Mapbox
  • “Estilos”, documentación de Mapbox
  • "Uso de variables Env en el código del lado del cliente", en "Modos y variables de entorno", Vue CLI