So erstellen Sie Karten mit React und Leaflet
Veröffentlicht: 2022-03-10Das Erfassen von Informationen aus einer CSV- oder einer JSON-Datei ist nicht nur kompliziert, sondern auch mühsam. Die Darstellung derselben Daten in Form einer visuellen Hilfe ist einfacher. In diesem Artikel werden wir die Orte der nicht medizinischen Brandvorfälle, auf die die SF-Feuerwehr reagierte, auf einer Karte darstellen.
Für dieses Tutorial verwenden wir die folgenden Tools:
- Flugblatt
Eine JavaScript-Bibliothek für interaktive Karten - Reagieren
Eine JavaScript-Bibliothek zum Erstellen von Benutzeroberflächen - React-Merkblatt
Reaktionskomponenten für Leaflet-Maps
Was ist ein Merkblatt?
Mit etwa 27.000 Sternen ist Leaflet.js eine der führenden Open-Source-JavaScript-Bibliotheken für mobilfreundliche interaktive Karten. Es nutzt HTML5 und CSS3 auf modernen Browsern, während es auch auf älteren Browsern zugänglich ist. Alles in allem unterstützt es alle primären Desktop- und Mobilplattformen.
Leaflet wiegt etwa 38 KB und funktioniert perfekt für grundlegende Dinge. Für zusätzliche Erweiterungen kann es mit einer Vielzahl von Plugins erweitert werden.
Viele Zeitungen, darunter NPR, Washington Post, Boston Globe und andere Organisationen, verwenden Leaflet für ihre detaillierten Datenprojekte.
Der San Francisco Chronicle zum Beispiel führte ein Projekt namens California Fire Tracker durch – eine interaktive Karte, die mithilfe von Leaflet Informationen über Waldbrände in ganz Kalifornien liefert. Sie lokalisierten nicht nur den Ursprung des Feuers, sondern zeigten uns auch dessen Flugbahn.
Da dies ein einführendes Tutorial ist, werden wir nur die Orte der Brandereignisse markieren und einige Details dazu anzeigen.
Bevor wir zu React springen, wollen wir uns mit den Grundlagen von Leaflet vertraut machen. Dazu erstellen wir ein einfaches Beispiel, in dem wir eine Leaflet-Karte einrichten, mit Markierungen und Popups arbeiten.
Lassen Sie uns zunächst index.html- und app.js- Dateien in unserem /project
-Ordner erstellen und letztere mit unserer index.html -Datei verknüpfen.
Um mit der Verwendung von Leaflet zu beginnen, müssen wir Leaflet CSS und Leaflet JS in unseren Head-Tags verknüpfen. Beachten Sie, dass Leaflet CSS vor Leaflet JS kommt. Das war's für Leaflet.
Es gibt noch eine weitere Sache, die wir zu unserer index.html -Datei hinzufügen müssen – einen Container, der unsere Karte enthält.
<div></div>
Bevor wir es vergessen, geben wir unserem div Höhe.
#mapid { height: 1000px; }
Jetzt kommt der lustige Teil. Unabhängig davon, ob Sie sich entscheiden, eine neue JavaScript-Datei zu erstellen oder mit Skript-Tags fortzufahren, stellen Sie sicher, dass <div id="mapid">
zum Dom hinzugefügt wird, bevor L.map('mapid')
.
Sie fragen wahrscheinlich "Aber warum?" Nun, das liegt daran, dass Sie einen Fehler erhalten, wenn Sie die Karte an einen Container binden, der noch nicht existiert.
Uncaught Error: Map container not found
Erstellen einer Karte
Nun zum lustigen Teil. Um die Karte zu initialisieren, übergeben wir unser div mit einigen Optionen an L.map()
.
const myMap = L.map('mapid', { center: [37.7749, -122.4194], zoom: 13 })
Gehen wir Schritt für Schritt vor, um zu verstehen, was gerade passiert ist. Wir verwenden die Map-Klasse der Leaflet-API, um eine Karte auf der Seite zu erstellen. Wir übergeben dieser Klasse zwei Parameter:
- Wir haben eine Zeichenfolgenvariable übergeben, die die
DOM
-ID darstellt - Ein optionales Objektliteral mit Zuordnungsoptionen
Es gibt viele Optionen, die wir an unsere Klasse weitergeben könnten, aber die beiden wichtigsten Optionen sind die Mitte und der Zoom. Das Zentrum definiert ein anfängliches geografisches Zentrum der Karte, während Zoom eine anfängliche Zoomstufe der Karte angibt. Beide sind standardmäßig undefiniert.
Für das Zentrum gaben wir die Koordinaten von San Francisco ein. Es gibt viele Orte, an denen wir Vorwärts- und Rückwärts-Geokodierung durchführen können, aber für einfache Suchen wie diese können wir sie googeln.
Normalerweise hängt der Zoomwert davon ab, was Sie anzeigen möchten. Möchten Sie eine Stadt oder ein Bundesland zeigen? Land oder Kontinent? Spielen Sie mit dem Zoomwert herum, um eine bessere Vorstellung zu bekommen. Für dieses Beispiel haben wir 13 gewählt, weil es die gesamte Stadt zeigt.
Eine andere Möglichkeit, die Karte zu initialisieren, ist die Verwendung von setView(). Es nimmt die in einem Array von Koordinaten und eine Ganzzahl für die Zoomstufe.
const myMap = L.map('map').setView([37.7749, -122.4194], 13);
Standardmäßig sind alle Maus- und Berührungsinteraktionen auf der Karte aktiviert, und sie verfügt über Zoom- und Zuordnungssteuerelemente.
Erstellen einer Ebene
Als Nächstes fügen wir unserer Karte eine Kachelebene hinzu. In unserem Fall ist es eine Mapbox Streets-Kachelebene. Wir können verschiedene Arten von Kachelebenen anhängen, indem wir die TileLayer-Klasse instanziieren.
Um eine Kachelebene zu erstellen, müssen wir die URL-Vorlage für das Kachelbild, den Zuordnungstext und die maximale Zoomstufe der Ebene festlegen. Die URL-Vorlage ermöglicht uns den Zugriff auf die gewünschte Kachelebene des Dienstanbieters. Da wir die Static Tiles API von Mapbox verwenden, müssen wir ein Zugriffstoken anfordern.
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);
Wenn wir jetzt unsere index.html in einem Browser öffnen, sollten wir eine Karte von San Francisco sehen können. Lassen Sie uns eine Stecknadel auf die Karte setzen.
Markierungen und Kreise
Wir haben die Karte und die Ebene, aber sie zeigt uns nichts Bestimmtes. Um auf einen bestimmten Ort auf der Karte hinzuweisen, stellt Leaflet uns Markierungen zur Verfügung.
Um einen Standort zu fixieren, instanziieren wir den Marker mithilfe der Marker-Klasse, übergeben die Koordinaten und fügen ihn der Karte hinzu. Hier verwenden wir die Koordinaten von Twin Peaks in der Stadt.
const marker = L.marker([37.7544, -122.4477]).addTo(mymap);
Auf ähnliche Weise können wir mit einer Circle
-Klasse einen Kreis an die Karte binden. Wir übergeben einige optionale Optionen wie Radius, Farbe usw. Für die circle
übergeben wir die Koordinaten des Point Bonita Lighthouse.
const circle = L.circle([37.8157, -122.5295], { color: 'gold', fillColor: '#f03', fillOpacity: 0.5, radius: 200 }).addTo(mymap);
Popups
Das ist alles großartig, aber was ist, wenn wir noch mehr Informationen über den Standort weitergeben möchten? Wir tun dies mit Popup.
circle.bindPopup("I am pointing to Point Bonita Lighthouse"); marker.bindPopup("I am pointing to Twin Peaks");
Die bindPopup-Methode übernimmt einen bestimmten HTML-Inhalt und hängt ihn an die Markierung an, sodass das Popup angezeigt wird, wenn Sie auf die Markierung klicken.
React-Merkblatt
Jetzt wissen wir, wie man eine Karte erstellt und Markierungen mit Leaflet und Vanilla JavaScript hinzufügt. Mal sehen, wie wir mit React die gleichen Ergebnisse erzielen können. Wir werden nicht denselben Antrag stellen, sondern einen erweiterten Antrag stellen.
Die erste Aufgabe für uns besteht darin, ein Zugriffstoken vom San Francisco Open Data-Portal zu erhalten. Es ist ein Online-Portal, auf dem wir Hunderte von Datensätzen aus der Stadt und dem Landkreis San Francisco finden können. Ich habe mich für diese Ressource entschieden, aber es gibt viele andere Ressourcen, die wir stattdessen verwenden können.
Greifen Sie auf den API-Schlüssel zu
- Erstellen Sie ein Konto und melden Sie sich beim Portal an.
- Klicken Sie unten rechts auf den Link Verwalten.
- Klicken Sie auf Neuen API-Schlüssel erstellen und geben Sie ihm einen Namen.
- Kopieren Sie Ihre Schlüssel-ID und Ihr Schlüsselgeheimnis. Sie benötigen dies, um auf die Daten zuzugreifen.
Dazu verwenden wir React-Leaflet – Reaktionskomponenten für Leaflet-Maps. Lassen Sie uns eine Reaktions-App erstellen.
npx create-react-app react-fire-incidents cd react-fire-incidents
Dann installieren wir respond react-leaflet
und Leaflet, indem wir den folgenden Befehl in unserem Terminal ausführen:
npm install react-leaflet leaflet
App.js
Lassen Sie uns einen Ordner /components
in src
erstellen. Lassen Sie uns innerhalb von Komponenten eine Datei namens Map.js erstellen . Hier wird unsere Karte leben. Bearbeiten wir nun App.js , indem wir unnötigen Code entfernen und Module aus den Axios von „React react-leaflet axios
und der neu erstellten Map.js importieren .
import React, { Component, Fragment } from 'react'; import axios from 'axios'; import Map from './components/Map'
In unserer App-Klasse werden wir in unserem Zustand ein Array namens „Incidents“ definieren – wenn die Seite geladen wird, werden wir unsere Daten in dieses Array schieben.
class App extends Component { state = { incidents: [], } render() { return ( <div> </div> ); } } export default App;
Als Nächstes stellen wir eine GET-Anforderung, wenn die Komponente bereitgestellt wird. Wir haben das App-Token, aber wir brauchen noch einen Endpunkt. Wo finden wir den Endpunkt?
Gehen wir zum Portal und klicken Sie auf „Daten durchsuchen“. Lassen Sie uns in der Suchleiste nach Brandereignissen suchen. Das erste Ergebnis, das angezeigt wird, ist das, wonach wir suchen. Sobald wir auf den Link klicken, können wir die URL abrufen, indem wir oben rechts auf die API-Schaltfläche klicken.
Wir übergeben den Endpunkt an unsere GET-Anforderung und übergeben ein Limit und unser App-Token als Parameter. Die Originaldaten umfassen Tausende von Datensätzen, aber der Einfachheit halber haben wir sie auf 500 begrenzt. Wir aktualisieren unser Incidents-Array mit unseren Ergebnissen.
Sobald wir die Daten erhalten, aktualisieren wir unseren Status.
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 }); };
So sollte unsere App.js aussehen.
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;
Karte.js
Da wir bereits wissen, wie man eine Leaflet-Karte erstellt, wird dieser Teil relativ einfach sein. Wir werden Map
, TileLayer
, Marker
und Popup
-Komponenten aus der React react-leaflet
importieren.
import React, { Component } from 'react' import { Map, TileLayer, Marker, Popup } from 'react-leaflet'
Wenn wir uns an das vorherige Beispiel erinnern, brauchen wir Koordinaten und eine Zoomstufe, um die Karte zu initialisieren. In unserer Map
-Klasse definieren wir sie in unserem Zustand mit den Variablen lat
, lng
und zoom
.
export default class Map extends Component { state = { lat: 37.7749, lng: -122.4194, zoom: 13, } render() { return ( <div></div> ) } }
Dann prüfen wir, ob unser Array von Vorfällen leer ist. Wenn es leer ist, werden wir eine Nachricht mit dem Inhalt „Daten werden geladen“ zurückgeben; andernfalls geben wir eine Karte zurück.
In der Map
-Komponente unseres react-leaflet
übergeben wir Zentrumskoordinaten und eine Zoomstufe zusammen mit etwas Styling. In unserer TileLayer
Komponente übergeben wir Zuordnung und URL ähnlich wie in unserem vorherigen Beispiel.
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...' ) } }
Als nächstes durchlaufen wir unsere props.incident
und übergeben die Koordinaten jedes Vorfalls an die Marker-Komponente. Da React uns warnt, einen Schlüssel für jedes Element in einem Array zu übergeben, werden wir auch einen Schlüssel an Marker übergeben.
Innerhalb der Marker
Komponente übergeben wir eine Popup
Komponente. Ich habe einige Informationen über den Vorfall in das Popup eingefügt.
<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>
Und das ist es. Wenn wir unsere App ausführen und alles gut gelaufen ist, sollten wir in der Lage sein, eine Karte von San Francisco mit 500 Markierungen zu sehen, die uns auf die Orte der Feuervorfälle hinweisen. Wenn wir auf eine dieser Markierungen klicken, erscheint ein Popup mit weiteren Informationen über den Vorfall.
Einpacken
Obwohl wir viel behandelt haben, waren dies nur die Grundlagen. Leaflet ist ein sehr mächtiges Werkzeug, und wir können viele verschiedene Arten von Karten erstellen. Wenn Sie herumspielen möchten, versuchen Sie, eine weitere Ebene oder ein benutzerdefiniertes Symbol hinzuzufügen. Oder vielleicht möchten Sie eine interaktive Choropleth-Karte erstellen.