Jak tworzyć mapy za pomocą React i ulotek

Opublikowany: 2022-03-10
Szybkie podsumowanie ↬ Ulotka to bardzo potężne narzędzie, dzięki któremu możemy tworzyć wiele różnych rodzajów map. Ten samouczek pomoże Ci zrozumieć, jak stworzyć zaawansowaną mapę wraz z pomocą React i Vanilla JS.

Pobieranie informacji z pliku CSV lub JSON jest nie tylko skomplikowane, ale także nużące. Przedstawienie tych samych danych w formie pomocy wizualnej jest prostsze. W tym artykule przedstawimy na mapie lokalizacje niemedycznych incydentów pożarowych, na które zareagowała Straż Pożarna SF.

W tym samouczku wykorzystamy następujące narzędzia:

  • Ulotka
    Biblioteka JavaScript do interaktywnych map
  • Reagować
    Biblioteka JavaScript do budowania interfejsów użytkownika
  • Ulotka React
    Komponenty React do map ulotek

Co to jest ulotka?

Z około 27 tysiącami gwiazdek Leaflet.js jest jedną z wiodących bibliotek JavaScript typu open source dla interaktywnych map przyjaznych dla urządzeń mobilnych. Wykorzystuje HTML5 i CSS3 w nowoczesnych przeglądarkach, a jednocześnie jest dostępny w starszych. Podsumowując, obsługuje wszystkie podstawowe platformy stacjonarne i mobilne.

Ulotka waży około 38KB i doskonale sprawdza się w przypadku podstawowych rzeczy. Aby uzyskać dodatkowe rozszerzenia, można go rozszerzyć za pomocą ogromnej liczby wtyczek.

Wiele gazet, w tym między innymi NPR, Washington Post, Boston Globe i inne organizacje, korzysta z Leaflet do swoich szczegółowych projektów dotyczących danych.

Na przykład San Francisco Chronicle wykonało projekt o nazwie California Fire tracker — interaktywną mapę, która dostarcza informacji o pożarach lasów płonących w całej Kalifornii za pomocą Leaflet. Nie tylko wskazali źródło ognia, ale także pokazali nam jego trajektorię.

Ponieważ jest to samouczek wprowadzający, będziemy tylko zaznaczać lokalizacje incydentów pożarowych i wyświetlać kilka szczegółów na ich temat.

Zanim przejdziemy do React, zapoznajmy się z podstawami Leaflet. W tym celu stworzymy prosty przykład, w którym będziemy konfigurować mapę Leaflet, pracując ze znacznikami i wyskakującymi okienkami.

Więcej po skoku! Kontynuuj czytanie poniżej ↓

Najpierw utwórzmy pliki index.html i app.js w naszym folderze /project i połączmy je z naszym plikiem index.html .

Aby zacząć korzystać z Leaflet, musimy połączyć Leaflet CSS i Leaflet JS w naszych tagach head. Należy pamiętać, że Leaflet CSS występuje przed Leaflet JS. To tyle w przypadku ulotki.

Jest jeszcze jedna rzecz, którą musimy dodać do naszego pliku index.html — kontener, w którym będzie przechowywana nasza mapa.

 <div></div>

Zanim zapomnimy, dajmy wzrost naszemu div.

 #mapid { height: 1000px; }

Teraz zaczyna się zabawa. Niezależnie od tego, czy zdecydujesz się utworzyć nowy plik JavaScript, czy kontynuować w tagach skryptu, upewnij się, że <div id="mapid"> został dodany do dom przed wywołaniem L.map('mapid') .

Prawdopodobnie pytasz „Ale dlaczego?” Cóż, to dlatego, że spowoduje to błąd, jeśli powiążesz mapę z kontenerem, który jeszcze nie istnieje.

 Uncaught Error: Map container not found

Tworzenie mapy

Teraz przejdźmy do zabawnej części. Aby zainicjować mapę, przekazujemy w naszym div do L.map() z kilkoma opcjami.

 const myMap = L.map('mapid', { center: [37.7749, -122.4194], zoom: 13 })

Przejdźmy krok po kroku, aby zrozumieć, co się właśnie wydarzyło. Używamy klasy Map z Leaflet API do tworzenia mapy na stronie. Do tej klasy przekazujemy dwa parametry:

  1. Przekazaliśmy zmienną łańcuchową reprezentującą identyfikator DOM
  2. Opcjonalny literał obiektowy z opcjami mapy

Istnieje wiele opcji, które moglibyśmy przekazać naszej klasie, ale dwie główne opcje to środek i zoom. Środek określa początkowy środek geograficzny mapy, podczas gdy powiększenie określa początkowy poziom powiększenia mapy. Oba są domyślnie niezdefiniowane.

Do centrum minęliśmy współrzędne San Francisco. Istnieje wiele miejsc, w których możemy wykonać geokodowanie w przód i w tył, ale w przypadku podstawowego wyszukiwania, takiego jak to, możemy to wygooglować.

Zwykle wartość powiększenia zależy od tego, co chcesz wyświetlić. Chcesz pokazać miasto lub stan? Kraj czy kontynent? Śmiało i baw się wartością powiększenia, aby uzyskać lepszy pomysł. W tym przykładzie wybraliśmy 13, ponieważ pokazuje całe miasto.

Innym sposobem inicjalizacji mapy jest użycie setView(). Pobiera w tablicy współrzędnych i liczbę całkowitą dla poziomu powiększenia.

 const myMap = L.map('map').setView([37.7749, -122.4194], 13);

Domyślnie wszystkie interakcje myszy i dotyku na mapie są włączone, a także ma kontrolę nad powiększeniem i atrybucją.

Tworzenie warstwy

Następnie dodamy warstwę kafelków do naszej mapy; w naszym przypadku jest to warstwa kafelków Mapbox Streets. Możemy dołączyć różne typy warstw kafelków, tworząc instancję klasy TileLayer.

Aby utworzyć warstwę kafli, musimy ustawić szablon adresu URL dla obrazu kafelka, tekst przypisania i maksymalny poziom powiększenia warstwy. Szablon adresu URL daje nam dostęp do żądanej warstwy kafli od usługodawcy. Ponieważ używamy interfejsu Static Tiles API firmy Mapbox, będziemy musieli poprosić o token dostępu.

 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);

W tym momencie, jeśli otworzymy nasz index.html w przeglądarce, powinniśmy zobaczyć mapę San Francisco. Umieśćmy pinezkę na mapie.

Markery i koła

Mamy mapę i warstwę, ale nie wskazuje nam to niczego konkretnego. Aby wskazać konkretną lokalizację na mapie, Ulotka udostępnia nam znaczniki.

Aby przypiąć lokalizację, tworzymy wystąpienie znacznika za pomocą klasy Marker, przekazujemy współrzędne i dodajemy go do mapy. Tutaj używamy współrzędnych Twin Peaks w mieście.

 const marker = L.marker([37.7544, -122.4477]).addTo(mymap);

Podobnie możemy powiązać okrąg z mapą za pomocą klasy Circle . Przekazujemy kilka opcjonalnych opcji, takich jak promień, kolor i tak dalej. Do znacznika circle mijamy się we współrzędnych latarni Point Bonita.

 const circle = L.circle([37.8157, -122.5295], { color: 'gold', fillColor: '#f03', fillOpacity: 0.5, radius: 200 }).addTo(mymap);

Wyskakujące okienka

To wszystko świetnie, ale co, jeśli chcemy przekazać więcej informacji o lokalizacji. Robimy to za pomocą wyskakującego okienka.

 circle.bindPopup("I am pointing to Point Bonita Lighthouse"); marker.bindPopup("I am pointing to Twin Peaks");

Metoda bindPopup pobiera określoną zawartość HTML i dołącza ją do znacznika, więc wyskakujące okienko pojawia się po kliknięciu znacznika.

Ulotka React

Teraz wiemy, jak stworzyć mapę i dodać znaczniki za pomocą Leaflet i vanilla JavaScript. Zobaczmy, jak możemy osiągnąć te same wyniki dzięki React. Nie będziemy tworzyć tej samej aplikacji, ale zamiast tego stworzymy aplikację zaawansowaną.

Pierwszym zadaniem dla nas jest uzyskanie tokena dostępu z portalu San Francisco Open Data. To portal internetowy, w którym możemy znaleźć setki zbiorów danych z miasta i hrabstwa San Francisco. Zdecydowałem się skorzystać z tego zasobu, ale istnieje wiele innych zasobów, z których możemy skorzystać.

Dostęp do klucza API

  1. Załóż konto i zaloguj się do portalu.
  2. Kliknij łącze zarządzania w prawym dolnym rogu.
  3. Kliknij Utwórz nowy klucz API i nadaj mu nazwę.
  4. Skopiuj swój identyfikator klucza i klucz tajny. Potrzebujesz tego, aby uzyskać dostęp do danych.

W tym celu wykorzystamy React-Leaflet – komponenty React dla map Leaflet. Stwórzmy aplikację React.

 npx create-react-app react-fire-incidents cd react-fire-incidents

Następnie zainstalujemy react-leaflet i Leaflet, uruchamiając w naszym terminalu następującą komendę:

 npm install react-leaflet leaflet

App.js

Stwórzmy folder /components wewnątrz src . Wewnątrz komponentów stwórzmy plik o nazwie Map.js . To tutaj będzie mieszkać nasza Mapa. Teraz edytujmy App.js , usuwając zbędny kod i importując moduły z react-leaflet axios i nowo utworzonego Map.js.

 import React, { Component, Fragment } from 'react'; import axios from 'axios'; import Map from './components/Map'

W naszej klasie App zdefiniujemy tablicę w naszym stanie o nazwie incydenty — gdy strona się załaduje, przekażemy nasze dane do tej tablicy.

 class App extends Component { state = { incidents: [], } render() { return ( <div> </div> ); } } export default App;

Następnie po zamontowaniu komponentu wyślemy żądanie GET. Mamy token aplikacji, ale nadal potrzebujemy punktu końcowego. Gdzie znajdujemy punkt końcowy?

Przejdźmy do portalu i kliknij Przeglądaj dane. Na pasku wyszukiwania poszukajmy incydentów pożarowych. Pierwszym wynikiem, który się pojawia, jest to, czego szukamy. Po kliknięciu linku możemy uzyskać adres URL, klikając przycisk API w prawym górnym rogu.

Przekażemy punkt końcowy do naszego żądania GET i przekażemy limit oraz token aplikacji jako parametry. Oryginalne dane zawierają tysiące rekordów, ale dla uproszczenia ograniczyliśmy je do 500. Aktualizujemy tablicę incydentów o nasze wyniki.

Gdy otrzymamy dane, aktualizujemy nasz stan.

 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 }); };

Tak powinien wyglądać nasz App.js.

 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

Ponieważ wiemy już, jak stworzyć mapę Leaflet, ta część będzie stosunkowo łatwa. Importujemy komponenty Map , TileLayer , Marker , Popup z React react-leaflet Leaflet .

 import React, { Component } from 'react' import { Map, TileLayer, Marker, Popup } from 'react-leaflet'

Jeśli pamiętamy z poprzedniego przykładu, do inicjalizacji mapy potrzebne są współrzędne i poziom powiększenia. W naszej klasie Map definiujemy je w naszym stanie za pomocą zmiennych lat , lng i zoom .

 export default class Map extends Component { state = { lat: 37.7749, lng: -122.4194, zoom: 13, } render() { return ( <div></div> ) } }

Następnie sprawdzimy, czy nasza tablica incydentów jest pusta. Jeśli jest pusty, zwrócimy komunikat „Wczytywanie danych”; w przeciwnym razie zwrócimy mapę.

W komponencie Map w naszej react-leaflet przekażemy współrzędne środka i poziom powiększenia wraz z pewnym stylem. W naszym komponencie TileLayer przekażemy atrybucję i adres URL podobnie jak w naszym poprzednim przykładzie.

 render() { return ( this.props.incidents ? <Map center={[this.state.lat, this.state.lng]} zoom={this.state.zoom} style={{ width: '100%', height: '900px'}} > <TileLayer attribution='&copy <a href="https://osm.org/copyright">OpenStreetMap</a> contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> </Map> : 'Data is loading...' ) } }

Następnie zapętlamy nasz props.incident i przekazujemy współrzędne każdego incydentu do komponentu Marker. Ponieważ React ostrzega nas, abyśmy przekazali klucz do każdego elementu w tablicy, przekażemy również klucz do Markera.

Wewnątrz komponentu Marker przekazujemy komponent Popup . Dodałem informacje o incydencie w wyskakującym okienku.

 <Map center={[this.state.lat, this.state.lng]} zoom={this.state.zoom} style={{ width: '100%', height: '900px'}}> <TileLayer attribution='&copy <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 to jest to. Jeśli uruchomimy naszą aplikację i wszystko poszło dobrze, powinniśmy zobaczyć mapę San Francisco z 500 znacznikami wskazującymi miejsca pożarów. Jeśli klikniemy jeden z tych znaczników, pojawi się wyskakujące okienko z dodatkowymi informacjami o incydencie.

Zawijanie

Mimo że omówiliśmy dużo, to były tylko podstawy. Ulotka jest bardzo potężnym narzędziem i możemy tworzyć wiele różnych rodzajów map. Jeśli chcesz się pobawić, spróbuj dodać kolejną warstwę lub niestandardową ikonę. A może chciałbyś stworzyć interaktywną Kartogram.