Si quisieras desarrollar un proyecto relacionado con mapas en la web, seguro, lo primero que se te vendría en la cabeza es Google Maps, ya que es la referencia más conocida por todos los desarrolladores y hoy en día sigue manteniendo su liderazgo; para usarla requiere de crear cuentas personales e incluso necesitarías de una tarjeta de crédito ya que no es de libre acceso. Pero ¿Qué pasaría si quisieras usar una alternativa completamente gratuita? Te tengo la solución, y es la librería Leaflet.
Leaflet es una librería de código abierto que utiliza OpenStreetMap, es ligera y fácil de usar, en este post aprenderás a:
¡Te invito a quedarte!
Instalación y visualización de primer mapa con leaflet.
Lo primero que debemos hacer es realizar la instalación de la librería leaflet, dentro de nuestro proyecto de React Js ejecutamos el siguiente comando de instalación:npm i leaflet
Una vez que los paquetes se adicionen a nuestro archivo package.json, la librería leaflet necesita de CSS para renderizar el mapa y así visualizarse correctamente, para ello copia directamente esta etiqueta de _html _ en tu archivo index.html de tu proyecto de React Js.
<link
rel="stylesheet"
href="https://unpkg.com/[email protected]/dist/leaflet.css"
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin=""
/>
Después de pegar esta etiqueta se debe establecer un ancho y un alto a nuestro leaflet-container, con el propósito de que nuestro mapa se represente bien, de lo contrario no se visualizará, en este caso queremos que la dimensiones ocupen toda la pantalla, para esto debemos configurarlo de la siguiente manera:
.leaflet-container {
width: 100%;
height: 100vh;
}
Copia y pega las anteriores líneas de código en el archivo CSS del componente de tu proyecto y estaremos listos para comenzar a construir nuestro mapa.
Primer Mapa con react-leaflet
Se debe importar la librería ‘react-leaflet’ al nuestro proyecto, que en este caso es nuestro componente ChartMap, para este ejercicio vamos agregar los paquetes Map, Marker, Popup, TileLayer que más adelante te explicaré su uso.
Por ahora solo queremos visualizar un mapa, entonces debemos hacerlo dentro del componente Map del paquete ‘react-leaflet’. Este componente requiere una posición central, que es una matriz, y le debes asignar una longitud, una latitud y un nivel de zoom. Los datos que vamos a utilizar para este ejercicio provienen de unos sensores ubicados en la ciudad de Sogamoso-Boyacá Colombia, estos datos son ficticios. Por esta razón la asignación de las coordenadas se realiza en el sitio donde están ubicados lo sensores; es importante que en tu proyecto agregues las coordenadas que se ajusten a tus requerimientos, ya que si no las agregas te va arrojar un error. Posteriormente adicionamos la etiqueta <TileLayer> con los atributos que verás a continuación:
import React, { useState, useEffect } from'react';
import {Map, Marker, Popup, TileLayer} from"react-leaflet";
// import {Icon} from 'leaflet'import'./../assets/styles/ChartMap.styles.css';
const ChartMap = () => {
return (
<Mapcenter={[5.725,-72.940]} zoom={18}><TileLayerurl="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"attribution='© OpenStreetMap contributors'
/></<span class="hljs-name">Map>
);
};
export default ChartMap;
Los atributos de la etiqueta <TileLayer> requieren de OpenStreetMap y estamos obligados a ponerlos, cópialos tal cual, ya que si no lo haces se verá una pantalla gris y no se visualizará tu mapa. ¡De esta manera ya tenemos nuestro primer mapa!, como se muestra a continuación:
Visualizar nuestros Marcadores.
Ya que tenemos preparado nuestro entorno de trabajo, el siguiente paso es visualizar nuestros marcadores, pero antes debes tener listos tus datos. Para este proyecto se construyó una FAKE API, a partir de un archivo JSON, este archivo contiene los datos ficticios de 10 sensores con sus respectivos atributos como: fecha (‘Date_time’), código del sensor (‘Cod’), voltaje (‘Volt’), Temperatura canopy (‘CT’), Temperatura del sensor (‘ST’), Longitud (‘Long’), Latitud (‘Lat’); las coordenadas están ubicadas en la ciudad de Sogamoso-Boyacá. Con esta Fake Api podemos cargar los datos de manera local, pero tú puedes utilizar los datos que desees ya sea de un archivo JSON o una API. A continuación, te mostraré los datos que utilizaremos:
{
"sensors": [
{
"Date_Time": "2020-04-28 16:44:00",
"Cod": "1",
"Volt": "6.2",
"CT": "21.1",
"ST": "18.2",
"Long": "-72.9397",
"Lat": "5.72501"
},
{
"Date_Time": "2020-04-28 07:27:39",
"Cod": "2",
"Volt": "6.3",
"CT": "20.1",
"ST": "18.2",
"Long": "-72.9397",
"Lat": "5.72501"
},
{
"Date_Time": "2020-04-28 07:27:40",
"Cod": "3",
"Volt": "6.4",
"CT": "21.2",
"ST": "18.3",
"Long": "-72.9398",
"Lat": "5.72502"
},
{
"Date_Time": "2020-04-28 07:27:41",
"Cod": "4",
"Volt": "7.4",
"CT": "20.3",
"ST": "18.4",
"Long": "-72.9399",
"Lat": "5.72503"
},
{
"Date_Time": "2020-04-28 07:27:42",
"Cod": "5",
"Volt": "7.1",
"CT": "21.4",
"ST": "18.5",
"Long": "-72.94",
"Lat": "5.72504"
},
{
"Date_Time": "2020-04-28 07:27:43",
"Cod": "6",
"Volt": "6.8",
"CT": "21.5",
"ST": "18.6",
"Long": "-72.9401",
"Lat": "5.72505"
},
{
"Date_Time": "2020-04-28 07:27:44",
"Cod": "7",
"Volt": "6.1",
"CT": "21.6",
"ST": "18.7",
"Long": "-72.9402",
"Lat": "5.72506"
},
{
"Date_Time": "2020-04-28 07:27:45",
"Cod": "8",
"Volt": "7.8",
"CT": "21.7",
"ST": "18.8",
"Long": "-72.9403",
"Lat": "5.72507"
},
{
"Date_Time": "2020-04-28 07:27:46",
"Cod": "9",
"Volt": "7.1",
"CT": "21.8",
"ST": "18.9",
"Long": "-72.9404",
"Lat": "5.72508"
},
{
"Date_Time": "2020-04-28 07:27:47",
"Cod": "10",
"Volt": "6.12",
"CT": "21.9",
"ST": "18.1",
"Long": "-72.9405",
"Lat": "5.72509"
}
],
"comments": [
{
"id": 1,
"body": "some comment",
"postId": 1
}
],
"profile": {
"name": "typicode"
}
}
Corremos nuestra Fake Api con el siguiente comando:
npx json-server initalState.json
Y de manera local en la siguiente dirección: http://localhost:3000/sensors obtenemos nuestros datos y estamos listos para utilizarla.
Si quieres aprender a crear y personalizar tu propia FAKE API para tus proyectos de React JS, te invito a tomar el Curso Práctico de React JS con el profesor Oscar Barajas Tavares de Platzi, donde te explicará a desarrollarla desde cero.
Finalmente estamos preparados para mapear nuestros datos, lo primero que debemos hacer es capturar y guardar los datos que provienen de nuestra FAKE API, para ello utilizaremos React Hooks: useEffect y useState, estos son unas características de React disponibles a partir de la versión 16.8, las cuales permiten agregar estados y ciclos de vida a nuestros componentes creados como funciones. Para este caso guardaremos los datos de nuestra FAKE API en la variable api. Si quieres aprender acerca de esta herramienta, nuevamente te invito a que tomes el Curso Práctico de React JS.
Ya que tenemos nuestros datos guardados en la variable api, vamos a utilizar el componente Marker, este debe ir dentro del componente Map, primero realizamos una condición dónde preguntemos si existen nuestros datos, es decir que sean mayor a cero, después utilizamos el loop map de _js _ para que recorra todas las posiciones de nuestros datos; y dentro de Marker debemos llamar las variables espaciales, siempre debe ir primero la Latitud y después la Longitud. Cómo se muestra a continuación:
/* eslint-disable no-loop-func */import React, { useState, useEffect } from 'react';
import {Map, Marker, Popup, TileLayer} from "react-leaflet";
// import {Icon} from 'leaflet'import'./../assets/styles/ChartMap.styles.css';
const ChartMap = () => {
const [api, setApi] = useState([]);
useEffect(() => {
fetch('http://localhost:3000/sensors')
.then((response) => response.json())
.then((data) => setApi(data));
}, []);
const [activePark, setActivePark] = React.useState(null);
return (
<Map center={[5.725, -72.940]} zoom={18}>
<TileLayer
url=<span class="hljs-string">"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© OpenStreetMap contributors'
/>
{ api.length >0 && (
{api.map((park,index) => (
<Marker
key={index}
position={[
park[<span class="hljs-string">'Lat'],
park['Long'],
]}
/>
))}
)}
</<span class="hljs-built_in">Map>
);
};
exportdefault ChartMap;
¡De esta manera ya tenemos nuestros marcadores en nuestro mapa!
Ventanas emergentes para los marcadores.
Este componente nos permite visualizar en una pequeña burbuja blanca, sobre nuestro marcador con solo un clic, en esta burbuja podemos añadirle la descripción que deseemos. Estas las podemos personalizar, ya que las creamos a partir de etiquetas de HTML y puedes mejorar su aspecto usando CSS, siéntete libre de cambiar su diseño.
Para este ejemplo solo vamos a visualizar ventanas emergente básicas, es decir sin diseño. La descripción que se representará está sujeta al contenido de cada ubicación del sensor, los datos que vamos a visualizar son los siguientes: código del sensor (‘Cod’), voltaje (‘Volt’), Temperatura canopy (‘CT’), Temperatura del sensor (‘ST’).
Dentro del componente Marker vamos a crear el prop onClick el cual llamará la función setActivePark que permitirá que el usuario haga clic en el marcador. Fuera del componente Marker pero dentro de Map debemos realizar una condición, preguntando si la acción activePark al darle clic es true entonces podemos mostrar una ventana emergente, para ello utilizaremos el componente Popup de ‘react-leaflet’. Dentro de él daremos la ubicación de latitud y la longitud utilizando la acción activePark. También se debe agregar la función onClose la cual permite que el usuario pueda cerrar la ventana emergente, dentro de la función se envía setActivePark(null), para que el usuario pueda cerrarla. Para la descripción de nuestra ventana agregamos en etiquetas h2 de html los atributos descritos anteriormente. El código queda de la siguiente forma:
/* eslint-disable no-loop-func */
import React, { useState, useEffect } from 'react';
import {Map, Marker, Popup, TileLayer} from "react-leaflet";
// import {Icon} from 'leaflet'import'./../assets/styles/ChartMap.styles.css';
const ChartMap = () => {
const [api, setApi] = useState([]);
useEffect(() => {
fetch('http://localhost:3000/sensors')
.then((response) => response.json())
.then((data) => setApi(data));
}, []);
const [activePark, setActivePark] = React.useState(null);
return (
<Map center={[<span class="hljs-number">5.725, -72.940]} zoom={18}>
<TileLayer
url=<span class="hljs-string">"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© OpenStreetMap contributors'
/>
{ api.length >0 && (
{api.map((park,index) => (
<Marker
key={index}
position={[
park[<span class="hljs-string">'Lat'],
park['Long'],
]}
onClick={() => {
setActivePark(park);
}}
/>
))}
{activePark && (
<Popup
position={[
activePark[<span class="hljs-string">'Lat'],
activePark['Long']
]}
onClose={() => {
setActivePark(null);
}}
>
CT: {activePark['CT']}
ST: {activePark['ST']}
V: {activePark['Volt']}
Cod: {activePark['Cod']}
</Popup>
)}
)}
</Map>
);
};
export default ChartMap;
Finalmente, cuando le des clic a cada marcador podrás visualizar la descripción asignada.
Como pudiste observar leaflet es una fantástica alternativa de mapeo, este paquete es muy fácil de usar, su gran ventaja es que es de código abierto y lo mejor ¡no se requiere clave API! Definitivamente vale la pena probarlo, además que su biblioteca es muy ligera solo con 40 kb de JS. Como dato adicional esta herramienta es utilizada por gigantes de la industria, como Pinterest, GitHub entre otros. Finalmente, el código fuente de este proyecto está disponible aquí https://github.com/marlacp/Example-React-Leaflet. Te invito a buscar más ejemplos en el sitio web React-Leaflet y por su puesto ¡nunca pares de aprender!
Excelente tutorial, me sirvió muchisimo. Muchas gracias 😃
Este tutorial salva la vida para un proyecto en el que estoy trabajando, muchas gracias 😊
Con gusto 😃