Cum se creează hărți cu React și Leaflet
Publicat: 2022-03-10Înțelegerea informațiilor dintr-un fișier CSV sau JSON nu este doar complicată, dar este și plictisitoare. Reprezentarea acelorași date sub formă de ajutor vizual este mai simplă. În acest articol, vom reprezenta locațiile incidentelor de incendiu non-medicale la care Departamentul de Pompieri din SF a răspuns pe o hartă.
Pentru acest tutorial, vom folosi următoarele instrumente:
- pliant
O bibliotecă JavaScript pentru hărți interactive - Reacţiona
O bibliotecă JavaScript pentru construirea de interfețe cu utilizatorul - React-pliant
Componentele React pentru hărțile Leaflet
Ce este prospectul?
Cu aproximativ 27.000 de stele, Leaflet.js este una dintre principalele biblioteci JavaScript open-source pentru hărți interactive prietenoase cu dispozitivele mobile. Profită de HTML5 și CSS3 pe browserele moderne, în timp ce este accesibil și pe cele mai vechi. Per total, acceptă toate platformele principale desktop și mobile.
Pliantul cântărește aproximativ 38 KB și funcționează perfect pentru lucruri de bază. Pentru extensii suplimentare, acesta poate fi extins cu o cantitate mare de plugin-uri.
O mulțime de ziare, inclusiv NPR, Washington Post, Boston Globe, printre altele, și alte organizații folosesc Leaflet pentru proiectele lor de date aprofundate.
San Francisco Chronicle, de exemplu, a realizat un proiect numit California Fire tracker - o hartă interactivă care oferă informații despre incendiile care arde în California, folosind Leaflet. Nu numai că au indicat cu exactitate originea incendiului, dar ne-au arătat și traiectoria acestuia.
Deoarece acesta este un tutorial introductiv, vom marca doar locațiile incidentelor de incendiu și vom afișa câteva detalii despre acesta.
Înainte de a intra în React, să înțelegem elementele de bază ale Leaflet. Pentru aceasta, vom crea un exemplu simplu în care vom configura o hartă Leaflet, lucrând cu marcatori și ferestre pop-up.
Mai întâi, să creăm fișiere index.html și app.js în folderul nostru /project
și să le legăm pe acesta din urmă la fișierul nostru index.html .
Pentru a începe să folosim Leaflet, trebuie să conectăm Leaflet CSS și Leaflet JS în etichetele noastre head. Un lucru de reținut este că Leaflet CSS vine înaintea Leaflet JS. Asta e pentru Leaflet.
Mai este un lucru pe care trebuie să-l adăugăm la fișierul nostru index.html — un container care va ține harta noastră.
<div></div>
Înainte să uităm, să dăm înălțime div-ului nostru.
#mapid { height: 1000px; }
Acum vine partea distractivă. Indiferent dacă decideți să creați un nou fișier JavaScript sau să continuați în etichetele de script, asigurați-vă că <div id="mapid">
este adăugat în dom înainte de a apela L.map('mapid')
.
Probabil vă întrebați „Dar, de ce?” Ei bine, pentru că vă va da o eroare dacă legați harta la un container care nu există încă.
Uncaught Error: Map container not found
Crearea unei hărți
Acum, la partea distractivă. Pentru a inițializa harta, trecem în div-ul nostru la L.map()
cu câteva opțiuni.
const myMap = L.map('mapid', { center: [37.7749, -122.4194], zoom: 13 })
Să mergem pas cu pas pentru a înțelege ce tocmai s-a întâmplat. Folosim clasa Map din API-ul Leaflet pentru a crea o hartă pe pagină. Trecem în această clasă doi parametri:
- Am trecut o variabilă șir care reprezintă ID-ul
DOM
- Un obiect literal opțional cu opțiuni de hartă
Există multe opțiuni pe care le-am putea transmite clasei noastre, dar principalele două opțiuni sunt centrul și zoomul. Centrul definește un centru geografic inițial al hărții, în timp ce zoom specifică un nivel inițial de zoom al hărții. Ambele sunt nedefinite implicit.
Pentru centru, am trecut în coordonatele San Francisco. Există o mulțime de locuri în care putem efectua geocodare înainte și inversă, dar pentru o căutare de bază ca aceasta, o putem căuta pe Google.
De obicei, valoarea pentru zoom va depinde de ceea ce doriți să afișați. Vrei să arăți un oraș sau un stat? Țară sau continent? Continuați și jucați-vă cu valoarea de zoom pentru a vă face o idee mai bună. Pentru acest exemplu, am ales 13 pentru că arată întregul oraș.
O altă modalitate de inițializare a hărții este prin utilizarea setView(). Preia o serie de coordonate și un număr întreg pentru nivelul de zoom.
const myMap = L.map('map').setView([37.7749, -122.4194], 13);
În mod implicit, toate interacțiunile cu mouse-ul și atingerea de pe hartă sunt activate și are comenzi de zoom și atribuire.
Crearea unui strat
Apoi, vom adăuga un strat de plăci pe harta noastră; în cazul nostru, este un strat de plăci Mapbox Streets. Putem adăuga diferite tipuri de straturi de plăci prin instanțierea clasei TileLayer.
Pentru a crea un strat de plăci, trebuie să setăm șablonul URL pentru imaginea de plăci, textul de atribuire și nivelul maxim de zoom al stratului. Șablonul URL este cel care ne oferă acces la stratul de plăci dorit de la furnizorul de servicii. Deoarece folosim API-ul Static Tiles de la Mapbox, va trebui să solicităm un token de acces.
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', { attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery (c) <a href="https://www.mapbox.com/">Mapbox</a>', maxZoom: 18, id: 'mapbox/streets-v11', accessToken: 'your.mapbox.access.token' }).addTo(mymap);
În acest moment, dacă deschidem index.html într-un browser, ar trebui să putem vedea o hartă a orașului San Francisco. Să aruncăm un ac pe hartă.
Markere și cercuri
Avem harta și stratul, dar nu ne indică nimic specific. Pentru a indica o anumită locație de pe hartă, Leaflet ne oferă marcatoare.
Pentru a fixa o locație, instanțiăm markerul folosind clasa Marker, transmitem coordonatele și îl adăugăm pe hartă. Aici folosim coordonatele Twin Peaks din oraș.
const marker = L.marker([37.7544, -122.4477]).addTo(mymap);
În mod similar, putem lega un cerc de hartă folosind o clasă Circle
. Introducem câteva opțiuni opționale, cum ar fi raza, culoarea și așa mai departe. Pentru marcajul circle
, trecem în coordonatele Farului Point Bonita.
const circle = L.circle([37.8157, -122.5295], { color: 'gold', fillColor: '#f03', fillOpacity: 0.5, radius: 200 }).addTo(mymap);
Ferestre pop-up
Toate acestea sunt grozave, dar dacă vrem să transmitem mai multe informații despre locație. Facem acest lucru folosind pop-up.
circle.bindPopup("I am pointing to Point Bonita Lighthouse"); marker.bindPopup("I am pointing to Twin Peaks");
Metoda bindPopup preia un conținut HTML specificat și îl adaugă la marcator, astfel încât fereastra pop-up apare când faceți clic pe marcator.
React-pliant
Acum știm cum să creăm o hartă și să adăugăm marcatori folosind Leaflet și vanilla JavaScript. Să vedem cum putem obține aceleași rezultate cu React. Nu vom face aceeași aplicație, ci vom face o aplicație avansată.
Prima sarcină pentru noi este să obținem un token de acces de la portalul San Francisco Open Data. Este un portal online unde putem găsi sute de seturi de date din orașul și județul San Francisco. Am decis să folosesc această resursă, dar există o mulțime de alte resurse pe care le putem folosi în schimb.
Accesați cheia API
- Faceți un cont și conectați-vă la portal.
- Faceți clic pe linkul de gestionare din dreapta jos.
- Faceți clic pe Creare cheie API nouă și dați-i un nume.
- Copiați ID-ul cheii și Secretul cheii. Ai nevoie de asta pentru a accesa datele.
Pentru aceasta, vom folosi componentele React-Leaflet – react pentru hărțile Leaflet. Să creăm o aplicație de reacție.
npx create-react-app react-fire-incidents cd react-fire-incidents
Apoi, să instalăm react-leaflet
și Leaflet rulând următoarea comandă în terminalul nostru:
npm install react-leaflet leaflet
App.js
Să creăm un folder /components
în interiorul src
. În interiorul componentelor, să creăm un fișier numit Map.js . Aici va locui harta noastră. Acum haideți să edităm App.js eliminând codul inutil și importând module din react-leaflet axios
și Map.js nou creat.
import React, { Component, Fragment } from 'react'; import axios from 'axios'; import Map from './components/Map'
În clasa noastră de aplicații, vom defini o matrice în starea noastră numită incidente - când pagina se încarcă, vom împinge datele noastre în această matrice.
class App extends Component { state = { incidents: [], } render() { return ( <div> </div> ); } } export default App;
În continuare, vom face o solicitare GET când se montează componenta. Avem indicativul pentru aplicație, dar mai avem nevoie de un punct final. Unde găsim punctul final?
Să ne îndreptăm către portal și să facem clic pe Răsfoire date. În bara de căutare, să căutăm incidente de incendiu. Primul rezultat care apare este ceea ce căutăm. Odată ce facem clic pe link, putem obține adresa URL făcând clic pe butonul API din dreapta sus.
Vom trece punctul final la cererea noastră GET și vom transmite o limită și tokenul nostru de aplicație ca parametri. Datele originale au mii de înregistrări, dar pentru a menține lucrurile simple, le-am limitat la 500. Actualizăm matricea de incidente cu rezultatele noastre.
Odată ce obținem datele, ne actualizăm starea.
async componentDidMount() { const res = await axios.get('https://data.sfgov.org/resource/wr8u-xric.json', { params: { "$limit": 500, "$$app_token": YOUR_APP_TOKEN } }) const incidents = res.data; this.setState({incidents: incidents }); };
Așa ar trebui să arate App.js-ul nostru.
class App extends Component { state = { incidents: [], } async componentDidMount() { const res = await axios.get('https://data.sfgov.org/resource/wr8u-xric.json', { params: { "$limit": 500, "$$app_token": YOUR_APP_TOKEN } }) const incidents = res.data; this.setState({incidents: incidents }); }; render() { return ( <Map incidents={this.state.incidents}/> ); } } export default App;
Map.js
Deoarece știm deja cum să creăm o hartă Leaflet, această parte va fi relativ ușoară. Vom importa componente Map
, TileLayer
, Marker
, Popup
din react-leaflet
.
import React, { Component } from 'react' import { Map, TileLayer, Marker, Popup } from 'react-leaflet'
Dacă ne amintim din exemplul anterior, avem nevoie de coordonate și un nivel de zoom pentru inițializarea hărții. În clasa noastră Map
, le definim în starea noastră folosind variabile lat
, lng
și zoom
.
export default class Map extends Component { state = { lat: 37.7749, lng: -122.4194, zoom: 13, } render() { return ( <div></div> ) } }
Apoi vom verifica dacă șirul nostru de incidente este gol. Dacă este gol, vom returna un mesaj care spune „Datele se încarcă”; în caz contrar, vom returna o hartă.
În componenta Map
a react-leaflet
, vom trece coordonatele centrale și un nivel de zoom împreună cu unele stiluri. În componenta noastră TileLayer
, vom transmite atribuirea și adresa URL similare cu exemplul nostru anterior.
render() { return ( this.props.incidents ? <Map center={[this.state.lat, this.state.lng]} zoom={this.state.zoom} style={{ width: '100%', height: '900px'}} > <TileLayer attribution='© <a href="https://osm.org/copyright">OpenStreetMap</a> contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> </Map> : 'Data is loading...' ) } }
Apoi, trecem peste props.incident
și trecem coordonatele fiecărui incident la componenta Marker. Deoarece React ne avertizează să transmitem o cheie fiecărui element dintr-o matrice, vom transmite o cheie și către Marker.
În interiorul componentei Marker
, trecem într-o componentă Popup
. Am adăugat câteva informații despre incident în fereastra pop-up.
<Map center={[this.state.lat, this.state.lng]} zoom={this.state.zoom} style={{ width: '100%', height: '900px'}}> <TileLayer attribution='© <a href="https://osm.org/copyright">OpenStreetMap</a> contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> { this.props.incidents.map(incident => { const point = [incident['point']['coordinates'][1], incident['point']['coordinates'][0]] return ( <Marker position={point} key={incident['incident_number']} > <Popup> <span>ADDRESS: {incident['address']}, {incident['city']} - {incident['zip_code']}</span> <br/> <span>BATTALION: {incident['battalion']}</span><br/> </Popup> </Marker> ) }) } </Map>
Și asta este. Dacă rulăm aplicația noastră și dacă totul a mers bine, ar trebui să putem vedea o hartă a orașului San Francisco cu 500 de marcaje care ne indică locațiile incidentelor de incendiu. Dacă facem clic pe unul dintre acești marcatori, va apărea o fereastră pop-up cu mai multe informații despre incident.
Încheierea
Chiar dacă am acoperit multe, acestea au fost doar elementele de bază. Leaflet este un instrument foarte puternic și putem crea o mulțime de tipuri diferite de hărți. Dacă doriți să vă jucați, încercați să adăugați un alt strat sau o pictogramă personalizată. Sau poate doriți să creați o hartă interactivă Choropleth.