Muchos posts sobre mapas, pero ahora vamos a ver cómo usar mapas de Mapbox con un componente que puede aprovechar cosas como el GPU del dispositivo donde se esté visualizando nuestro mapa.
Estos mismos mapas se pueden usar con un paquete hecho por el equipo de Uber: react-map-gl
Empecemos por crearnos una cuenta en la página de Mapbox y luego en la parte de nuestra cuenta podemos ver nuestro Access token para poder utilizar los mapas.
Si quieren arrancar desde cero pueden seguir los pasos de mi post Up and running con ParcelJS, o sino cree un repo en Github con los pasos del post ya realizados 😁
Una vez que tengamos el proyecto base preparado, podemos usar la magia ✨ de ParcelJS y hacer el import MapGL from 'react-map-gl'
al principio
de nuestro archivo y guardar (siempre y cuando tengamos nuestro servidor de desarrollo corriendo), o podemos frenar el servidor de desarrollo si es que
lo tenemos corriendo e instalamos el paquete react-map-gl
:
yarn add react-map-gl
npm i react-map-gl
Y volvemos a levantar el servidor con yarn start
o npm start
.
Una vez hecho eso, tengamos nuestro Access token preferentemente guardado en una variable de entorno MAPBOX_TOKEN
, para eso creamos en la raíz de nuestro
proyecto un archivo que se llame .env
y dentro ponemos lo siguiente:
MAPBOX_TOKEN=pk.eyJ1IjoiYWd1c3Rpbm11bGV0IiwiYSI6ImNrOW9reHF0ZXXXXXXXXXXXXXXXXXXXXXXXXX
Obviamente con un token real. Luego en el frontend podemos acceder a este valor usando process.env.MAPBOX_TOKEN
, aunque al momento de usarlo si ven que
no lo toma, no desesperen: frenen y vuelvan a correr el servidor de desarrollo y si eso no les funciona, borren la carpeta .cache
y vuelvan a levantar el servidor.
Ahora vamos a nuestro front a usar nuestro paquete recién instalado, que acepta algunas props:
<MapGL
{...viewport}
width="100vw"
height="50vh"
mapStyle="mapbox://styles/mapbox/dark-v10"
onViewportChange={nextViewport => setViewport(nextViewport)}
mapboxApiAccessToken={process.env.MAPBOX_TOKEN}
/>
Mmmm pero qué es ese viewport y onViewportChange? 🤔 viewport son los valores que debería tener como inicial nuestro mapa (latitud, longitud, etc.) y onViewportChange
es lo que nos permite ir moviéndonos en el mapa, lo que nos da a entender que necesitamos usar State en nuestro componente, ya que tenemos unas variables que van a
ir cambiando con el tiempo, importemos entonces useState
y creemos el viewport (yo lo voy a crear con las coordenadas de Buenos Aires, Argentina, ya que
ahí es donde vivo):
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import MapGL from 'react-map-gl';
const App = () => {
const [viewport, setViewport] = useState({
latitude: -34.6037,
longitude: -58.3816,
zoom: 14,
bearing: 0,
pitch: 0
});
return (
<MapGL
{...viewport}
width="100vw"
height="50vh"
mapStyle="mapbox://styles/mapbox/dark-v10"
onViewportChange={nextViewport => setViewport(nextViewport)}
mapboxApiAccessToken={process.env.MAPBOX_TOKEN}
/>
);
}
ReactDOM.render(<App/>, document.getElementById('root'))
Y con eso debería func-... Cómo que no funciona? _typeof
qué? Que falta un archivo CSS? 😭😭😭😭
En el post de ParcelJS les dije que las soluciones "zero configuration" pueden traer algunas contras o complicaciones, así que vamos a ir tacleando estos dos problemas:
Este archivo lo podemos encontrar en la carpeta node_modules
dentro del paquete mapbox-gl
, que es una dependencia del que instalamos antes.
Para importarlo, debemos agregar import 'mapbox-gl/dist/mapbox-gl.css
junto a nuestros imports.
Este error me trajo muchos dolores de cabeza a mí y a muchas otras personas más, estuve recorriendo muchos issues de github hasta que encontré este issue
de Dan Abramov diciendo que hay que desactivar el plugin-transform-typeof-symbol
porque básicamente secuestra los typeof
del código y los cambia por otro.
Ahora, cómo podemos desactivarlo? Para eso encontré que en ParcelJS se puede instalar y configurar Babel 7
para usar loose
mode con el babel-preset-env
. No me expliqué muy bien pero creo que se va a entender mejor si ponemos manos a la obra:
Instalemos Babel como dependencia de desarrollo en nuestro proyecto:
yarn add -D @babel/core @babel/cli
npm i --save-dev @babel/core @babel/cli
Y ahora creemos un archivo en la raíz de nuestro proyecto que se llame .babelrc
, con la siguiente configuración:
{
"presets": [
[
"@babel/env",
{
"loose": true,
"targets": {
"browsers": [
">2%",
"last 1 Edge version",
"last 2 Safari version",
"last 1 Firefox version"
]
},
}
]
]
}
Qué estamos haciendo en este archivo? Configurando babel-preset-env
para usar el modo loose
y evitar que el plugin transform-typeof-symbol
corra. Con
targets
indicamos sobre qué navegadores queremos que suceda esto, pero eso queda para otra historia. Espero igual que se haya entendido mejor la explicación de antes.
Ahora corremos nuestro proyecto (tarda un poco más ya que tiene que crear todo con la config nueva) y deberíamos tener nuestro mapa funcionando correctamente 😀
No sé si notaron pero hay una prop que es mapStyle
, lo que indica que podemos cambiar los estilos de nuestro mapa, pueden cambiarlos por cualquiera de los que
están acá en la documentación de Mapbox.
Invito a que investiguen qué se puede hacer con react-map-gl
, poner Markers creo que es más fácil que
con LeafletJS y pueden también ver la parte de Ejemplos donde se hace uso de los Layers y se aprovecha el GPU.
Espero que todo esto les sirva y que los mapas no les hagan doler la cabeza como a mí, nos vemos en el próximo post!