React 및 Leaflet으로 지도를 만드는 방법

게시 됨: 2022-03-10
빠른 요약 ↬ 전단지는 매우 강력한 도구이며 다양한 종류의 지도를 만들 수 있습니다. 이 튜토리얼은 React 및 Vanilla JS의 도움으로 고급 지도를 만드는 방법을 이해하는 데 도움이 됩니다.

CSV 또는 JSON 파일에서 정보를 파악하는 것은 복잡할 뿐만 아니라 지루합니다. 동일한 데이터를 시각 자료의 형태로 표현하는 것이 더 간단합니다. 이 글에서는 SF소방서에서 대응한 비의료적 화재 사건의 위치를 ​​지도에 표시해 보겠습니다.

이 튜토리얼에서는 다음 도구를 사용할 것입니다.

  • 전단
    대화형 지도용 JavaScript 라이브러리
  • 반응
    사용자 인터페이스 구축을 위한 JavaScript 라이브러리
  • 리액트 리플렛
    전단지 맵에 대한 React 구성 요소

전단지 란 무엇입니까?

약 27,000개의 별을 보유한 Leaflet.js는 모바일 친화적인 대화형 지도를 위한 최고의 오픈 소스 JavaScript 라이브러리 중 하나입니다. 최신 브라우저에서 HTML5 및 CSS3을 활용하는 동시에 이전 브라우저에서도 액세스할 수 있습니다. 대체로 모든 기본 데스크톱 및 모바일 플랫폼을 지원합니다.

전단지의 무게는 약 38KB이며 기본적인 작업에 완벽하게 작동합니다. 추가 확장의 경우 방대한 양의 플러그인으로 확장할 수 있습니다.

NPR, Washington Post, Boston Globe 및 기타 조직을 비롯한 많은 신문에서 심층 데이터 프로젝트에 Leaflet을 사용합니다.

예를 들어 San Francisco Chronicle은 California Fire tracker라는 프로젝트를 수행했습니다. 이 프로젝트는 Leaflet을 사용하여 캘리포니아 전역에서 타는 산불에 대한 정보를 제공하는 대화형 지도입니다. 그들은 화재의 기원을 정확히 지적했을 뿐만 아니라 화재의 궤적도 보여주었습니다.

이것은 입문용 튜토리얼이므로 화재 발생 위치만 표시하고 이에 대한 일부 세부 정보를 표시합니다.

React를 시작하기 전에 Leaflet의 기본을 이해합시다. 이를 위해 전단지 맵을 설정하고 마커 및 팝업을 사용하는 간단한 예제를 만들 것입니다.

점프 후 더! 아래에서 계속 읽기 ↓

먼저 /project 폴더에 index.htmlapp.js 파일을 만들고 후자를 index.html 파일에 연결합니다.

Leaflet 사용을 시작하려면 head 태그에 Leaflet CSS와 Leaflet JS를 연결해야 합니다. 한 가지 명심해야 할 점은 Leaflet CSS가 Leaflet JS보다 먼저 온다는 것입니다. 그것이 전단지를위한 것입니다.

index.html 파일에 추가해야 할 것이 하나 더 있습니다. 지도를 담을 컨테이너입니다.

 <div></div>

잊어버리기 전에 div에 높이를 지정해 보겠습니다.

 #mapid { height: 1000px; }

이제 재미있는 부분이 나옵니다. 새 JavaScript 파일을 생성하기로 결정하든 스크립트 태그에서 계속하기로 결정하든 L.map('mapid') 을 호출하기 전에 <div id="mapid"> 가 dom에 추가되었는지 확인하십시오.

당신은 아마도 "하지만, 왜?"라고 물을 것입니다. 아직 존재하지 않는 컨테이너에 맵을 바인딩하면 오류가 발생하기 때문입니다.

 Uncaught Error: Map container not found

지도 만들기

이제 재미있는 부분으로. 지도를 초기화하기 위해 몇 가지 옵션을 사용하여 div를 L.map() 에 전달합니다.

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

방금 무슨 일이 일어났는지 이해하기 위해 단계별로 가봅시다. Leaflet API의 Map 클래스를 사용하여 페이지에 지도를 생성합니다. 이 클래스에 두 개의 매개변수를 전달합니다.

  1. DOM ID를 나타내는 문자열 변수를 전달했습니다.
  2. 맵 옵션이 있는 선택적 객체 리터럴

클래스에 전달할 수 있는 많은 옵션이 있지만 주요 두 가지 옵션은 중앙과 확대/축소입니다. 중심은 지도의 초기 지리적 중심을 정의하는 반면 확대/축소는 초기 지도 확대/축소 수준을 지정합니다. 둘 다 기본적으로 정의되어 있지 않습니다.

센터의 경우 샌프란시스코 좌표를 전달했습니다. 정방향 및 역방향 지오코딩을 수행할 수 있는 곳이 많이 있지만 이와 같은 기본 검색의 경우 Google에서 검색할 수 있습니다.

일반적으로 확대/축소 값은 표시하려는 항목에 따라 다릅니다. 도시 또는 주를 표시하시겠습니까? 국가 또는 대륙? 더 나은 아이디어를 얻으려면 확대/축소 값을 가지고 놀아보세요. 이 예에서는 도시 전체를 보여주기 때문에 13을 선택했습니다.

지도를 초기화하는 또 다른 방법은 setView()를 사용하는 것입니다. 좌표 배열과 확대/축소 수준에 대한 정수를 사용합니다.

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

기본적으로 지도의 모든 마우스 및 터치 상호 작용이 활성화되어 있으며 확대/축소 및 속성 컨트롤이 있습니다.

레이어 생성

다음으로 지도에 타일 레이어를 추가합니다. 우리의 경우 Mapbox Streets 타일 레이어입니다. TileLayer 클래스를 인스턴스화하여 다양한 유형의 타일 레이어를 추가할 수 있습니다.

타일 ​​레이어를 생성하려면 타일 이미지, 속성 텍스트, 레이어의 최대 확대/축소 수준에 대한 URL 템플릿을 설정해야 합니다. URL 템플릿은 서비스 제공자로부터 원하는 타일 레이어에 대한 액세스를 제공합니다. Mapbox의 Static Tiles API를 사용하고 있으므로 액세스 토큰을 요청해야 합니다.

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

이 시점에서 브라우저에서 index.html을 열면 샌프란시스코 지도를 볼 수 있어야 합니다. 지도에 핀을 놓읍시다.

마커와 원

지도와 레이어가 있지만 특정 항목을 가리키지는 않습니다. 지도의 특정 위치를 가리키기 위해 Leaflet은 마커를 제공합니다.

위치를 고정하려면 Marker 클래스를 사용하여 마커를 인스턴스화하고 좌표를 전달한 다음 지도에 추가합니다. 여기서는 도시의 Twin Peaks 좌표를 사용합니다.

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

마찬가지로 Circle 클래스를 사용하여 원을 지도에 바인딩할 수 있습니다. 반경, 색상 등과 같은 몇 가지 선택적 옵션을 전달합니다. circle 마커의 경우 Point Bonita Lighthouse의 좌표를 전달합니다.

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

팝 업

이 모든 것이 훌륭하지만 위치에 대한 추가 정보를 전달하려면 어떻게 해야 할까요? 팝업을 사용하여 이 작업을 수행합니다.

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

bindPopup 메소드는 지정된 HTML 컨텐츠를 가져와서 마커에 추가하므로 마커를 클릭하면 팝업이 나타납니다.

리액트 리플렛

이제 지도를 만들고 Leaflet과 바닐라 JavaScript를 사용하여 마커를 추가하는 방법을 알게 되었습니다. React로 어떻게 같은 결과를 얻을 수 있는지 봅시다. 우리는 같은 응용 프로그램을 만들지 않고 대신 고급 응용 프로그램을 만들 것입니다.

우리의 첫 번째 작업은 샌프란시스코 오픈 데이터 포털에서 액세스 토큰을 얻는 것입니다. 샌프란시스코 시와 카운티에서 수백 개의 데이터 세트를 찾을 수 있는 온라인 포털입니다. 이 리소스를 사용하기로 결정했지만 대신 사용할 수 있는 다른 리소스가 많이 있습니다.

액세스 API 키

  1. 계정을 만들고 포털에 로그인합니다.
  2. 오른쪽 하단에 있는 관리 링크를 클릭합니다.
  3. 새 API 키 만들기를 클릭하고 이름을 지정합니다.
  4. 키 ID와 키 암호를 복사합니다. 데이터에 액세스하려면 이것이 필요합니다.

이를 위해 React-Leaflet – Leaflet 맵에 대한 반응 구성 요소를 사용합니다. 반응 앱을 만들어 봅시다.

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

그런 다음 터미널에서 다음 명령을 실행하여 react-leaflet 및 Leaflet을 설치해 보겠습니다.

 npm install react-leaflet leaflet

앱.js

src 안에 /components 폴더를 생성합시다. 컴포넌트 내부에 Map.js 라는 파일을 생성해 보겠습니다. 이곳이 우리 지도가 살 곳입니다. 이제 불필요한 코드를 제거하고 react-leaflet axios axios 및 새로 생성된 Map.js 에서 모듈을 가져와서 App.js 를 편집해 보겠습니다.

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

App 클래스에서 인시던트라는 상태의 배열을 정의할 것입니다. 페이지가 로드될 때 데이터를 이 배열로 푸시합니다.

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

다음으로 구성 요소가 마운트될 때 GET 요청을 수행합니다. 앱 토큰이 있지만 여전히 엔드포인트가 필요합니다. 끝점은 어디에서 찾을 수 있습니까?

포털로 이동하여 데이터 찾아보기를 클릭해 보겠습니다. 검색창에서 화재사고를 검색해 봅시다. 표시되는 첫 번째 결과는 우리가 찾고 있는 것입니다. 링크를 클릭하면 오른쪽 상단의 API 버튼을 클릭하여 URL을 얻을 수 있습니다.

엔드포인트를 GET 요청에 전달하고 제한과 앱 토큰을 매개변수로 전달합니다. 원본 데이터에는 수천 개의 레코드가 있지만 간단하게 유지하기 위해 500개로 제한했습니다. 결과로 사건 배열을 업데이트합니다.

데이터를 받으면 상태를 업데이트합니다.

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

이것이 우리의 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;

맵.js

우리는 이미 전단지 맵을 만드는 방법을 알고 있기 때문에 이 부분은 비교적 쉬울 것입니다. react-leaflet 에서 Map , TileLayer , Marker , Popup 구성 요소를 가져올 것입니다.

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

이전 예에서 기억한다면 지도를 초기화하기 위한 좌표와 확대/축소 수준이 필요합니다. Map 클래스에서 lat , lngzoom 변수를 사용하여 상태에서 정의합니다.

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

그런 다음 인시던트 배열이 비어 있는지 확인합니다. 비어 있으면 "Data is Loading"이라는 메시지가 반환됩니다. 그렇지 않으면 지도를 반환합니다.

react-leafletMap 구성 요소에서 일부 스타일과 함께 중심 좌표와 확대/축소 수준을 전달합니다. TileLayer 구성 요소에서 이전 예제와 유사한 속성 및 URL을 전달합니다.

 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...' ) } }

다음으로 props.incident 를 반복하고 모든 사건의 좌표를 Marker 구성 요소에 전달합니다. React는 배열의 모든 항목에 키를 전달하라고 경고하므로 Marker에도 키를 전달합니다.

Marker 구성 요소 내부에서 Popup 구성 요소를 전달합니다. 나는 팝업 안에 사건에 대한 몇 가지 정보를 추가했습니다.

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

그리고 이것이다. 앱을 실행하고 모든 것이 잘되면 화재 발생 위치를 가리키는 500개의 마커가 있는 샌프란시스코 지도를 볼 수 있습니다. 해당 마커 중 하나를 클릭하면 사건에 대한 추가 정보가 포함된 팝업이 나타납니다.

마무리

우리는 많은 것을 다루었지만 이것은 단지 기본이었습니다. 전단지는 매우 강력한 도구이며 다양한 종류의 지도를 만들 수 있습니다. 놀고 싶다면 다른 레이어나 사용자 정의 아이콘을 추가해 보세요. 또는 대화식 Choropleth Map을 만들고 싶을 수도 있습니다.