React-Leaflet v3: Создание картографического приложения
Вот код созданного нами компонента Leaflet:
Это прекрасно работает, но наш код не очень похож на React, поскольку мы манипулируем DOM с помощью vanilla Leaflet и рендерим все в один div «map». Давайте рассмотрим, как создать правильное приложение сопоставления React с открытым исходным кодом с помощью React-Leaflet.
Некоторые вещи, которые следует помнить
Важно помнить, что React-Leaflet не заменяет Leaflet. Он просто предоставляет способ создания слоев Leaflet в качестве компонентов React, вместо использования настройки useRef/ useEffect, как мы использовали в нашем приложении vanilla-Leaflet / React. Это означает, что наши компоненты React-Leaflet могут вести себя иначе, чем стандартный компонент React. Из документации React-Leaflet:
Рендеринг DOM
React не отображает слои Leaflet в DOM, этот рендеринг выполняется самим Leaflet. React визуализирует элемент <div> только при визуализации компонента MapContainer, содержимого компонентов слоев пользовательского интерфейса.
Помните, как мы отрендерили все в один div на карте vanilla Leaflet? React-Leaflet делает то же самое за кулисами!
Свойства компонента
Свойства, переданные компонентам, используются для создания соответствующего экземпляра Leaflet при первом рендеринге компонента и по умолчанию должны рассматриваться как неизменяемые.
Во время первого рендеринга все эти свойства должны поддерживаться, как и Leaflet, однако они не будут обновляться в пользовательском интерфейсе при изменении, если они явно не задокументированы как изменяемые.
Изменения изменяемых свойств сравниваются по ссылке (если не указано иное) и применяются, вызывая соответствующий метод для экземпляра элемента Leaflet.
Опять же, это очень похоже на нашу карту vanilla Leaflet. Элементы-листовки создаются только при первом монтировании компонента, точно так же, как мы использовали хук useEffect, а затем модифицировали его с помощью refs.
Реагирование на контекст
React Leaflet использует контекстный API React, чтобы сделать некоторые экземпляры элементов Leaflet доступными для дочерних элементов, которые в этом нуждаются.
Каждый экземпляр карты Leaflet имеет свой собственный контекст React, созданный компонентом MapContainer. Другие компоненты и хуки, предоставляемые React Leaflet, могут использоваться только как потомки MapContainer.
React-Leaflet использует контекстный API, чтобы сделать свои экземпляры и состояние доступными для всех своих дочерних элементов. Вы увидите пример этого, как только мы перейдем к тому, как мы обрабатываем события карты.
Начинаем
Чтобы упростить настройку, у меня есть стартер, который вы можете использовать на Stack Blitz. Если вы предпочитаете следовать инструкциям на своем локальном компьютере, ознакомьтесь с разделом документации по установке. Не забудьте установить Leaflet, а также React-Leaflet! Также обратите внимание, что в этой демонстрации мы будем использовать некоторые стили и компоненты из Material-UI.
В public/index.html, мы можем вставить ссылку CDN для файлов CSS и Javascript Leaflet:
index.html
<!-- CSS -->
<link
rel="stylesheet"
href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
crossorigin=""
/>
<!-- JS -->
<script
src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
crossorigin=""
></script>
Теперь мы можем настроить наш MapContainer и наш слой листов карты. MapContainer - это то, что создает экземпляр карты Leaflet и совместно использует этот экземпляр со всеми его дочерними элементами через контекстный API. Для наших целей мы только передадим center, zoom, style и zoomControl в MapContainer на данный момент, но ознакомьтесь с этим списком реквизитов, которые вы можете передать для последующего использования. Мы будем центрировать нашу карту по Соединенным Штатам ( [37.0902, -95.7129]), установив zoom для 3, и установив zoomControl для false,так как мы добавим его немного позже. У опоры style также должны быть установлены высота и ширина.
В src/map мы можем создать новый файл с именем Map.jsx, а затем импортировать его в наш файл App.js:
Map.jsx
import React from 'react'
import { MapContainer, TileLayer } from 'react-leaflet'
const Map = () => {
return (
<>
<MapContainer
center={[37.0902, -95.7129]}
zoom={3}
zoomControl={false}
style={{ height: '100vh', width: '100%' }}
>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
</MapContainer>
</>
)
}
export default Map
App.jsx
import React from "react";
import "./assets/css/style.css";
import { Container } from "@material-ui/core";
import Map from "./map/Map";
export default function App() {
return (
<Container disableGutters>
<Map />
</Container>
);
}
Теперь у вас на экране должна быть пустая карта, которая выглядит примерно так:
Добавление элементов управления
Теперь, когда у нас есть наша карта, давайте добавим ZoomControl и LayersControl.
ZoomControl добавить очень просто. Нам нужно импортировать компонент ZoomControl и разместить его прямо под компонентом TileLayer. Мы также хотим передать ему опору position со значением 'topright':
Map.jsx
import React from 'react'
import { MapContainer, TileLayer, ZoomControl } from 'react-leaflet'
const Map = () => {
return (
<>
<MapContainer
center={[37.0902, -95.7129]}
zoom={3}
zoomControl={false}
style={{ height: '100vh', width: '100%' }}
>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<ZoomControl position='topright'/>
</MapContainer>
</>
)
}
export default Map
LayersControl немного по-другому. Мы можем импортировать этот компонент и поместить его прямо над только что установленным ZoomControl. Затем мы используем LayersControl.BaseLayers и LayersControl.Overlay чтобы добавить наши слои к элементу управления. Мы будем использовать компонент LayersControl.Overlay для включения и выключения таких слоев, как маркеры и круги, на карте позже, а пока мы поместим компонент TileLayer внутрь компонента LayersControl.BaseLayers. Давайте также добавим вторую опцию плитки карты, чтобы мы действительно могли использовать наш элемент управления слоем. Перейдите к демонстрации Leaflet-Providers и выберите вторую плитку для использования, а затем настройте свой код следующим образом:
Map.jsx
import React from 'react'
import { MapContainer, TileLayer, ZoomControl, LayersControl } from 'react-leaflet'
const Map = () => {
return (
<>
<MapContainer
center={[37.0902, -95.7129]}
zoom={3}
zoomControl={false}
style={{ height: '100vh', width: '100%' }}
>
<LayersControl position="topright">
{/*
Give the layer a name that will be displayed inside of the layers control.
We also want to pass the checked prop to whichever map tile we want
displayed as the default:
*/}
<LayersControl.BaseLayer checked name="Basic Map">
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
</LayersControl.BaseLayer>
{/*
Add the second maptile:
*/}
<LayersControl.BaseLayer name="Topo Map">
<TileLayer
attribution='Map data: © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: © <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
url="https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png"
/>
</LayersControl.BaseLayer>
</LayersControl>
<ZoomControl position='topright'/>
</MapContainer>
</>
)
}
export default Map
Доступ к экземпляру карты и обработчикам событий
Вспомните раздел "Что нужно помнить" в этой статье. Мы узнали, что MapContainer делает экземпляр карты Leaflet доступным для своих потомков и что хуки для доступа к этому состоянию доступны только его потомкам. Из-за этого нам выгодно отделить логику MapContainer от логики слоя. В src/map, давайте создадим новый файл с именем Layers.jsx и копипастнем наш компонент LayersControl здесь:
Layers.jsx
import React from 'react'
import { TileLayer, LayersControl } from 'react-leaflet'
const Layers = () => {
return (
<>
<LayersControl position="topright">
<LayersControl.BaseLayer checked name="Basic Map">
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
</LayersControl.BaseLayer>
<LayersControl.BaseLayer name="Topo Map">
<TileLayer
attribution='Map data: © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: © <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
url="https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png"
/>
</LayersControl.BaseLayer>
</LayersControl>
</>
)
}
export default Layers
Map.jsx
import React from 'react'
import { MapContainer, ZoomControl } from 'react-leaflet'
import Layers from './Layers'
const Map = () => {
return (
<>
<MapContainer
center={[37.0902, -95.7129]}
zoom={3}
zoomControl={false}
style={{ height: '100vh', width: '100%' }}
>
<Layers />
<ZoomControl position='topright'/>
</MapContainer>
</>
)
}
export default Map
Экземпляр карты Leaflet имеет множество методов, доступных для получения и установки его состояния. Чтобы использовать эти методы, React-Leaflet предоставляет нам хук useMap. Скажем, мы хотим получить начальные границы и уровень масштабирования нашей карты. Мы могли бы вызвать useMap в верхней части нашего компонента и присвоить его переменной, скажем map, а затем ссылаться на эту переменную всякий раз, когда мы хотим использовать метод карты Leaflet:
Layers.jsx
import React from 'react'
// Import the useMap hook:
import { useMap, TileLayer, LayersControl } from 'react-leaflet'
const Layers = () => {
// Call useMap:
const map = useMap()
// Use the map methods:
console.log("Map Bounds:", map.getBounds())
console.log("Zoom Level:", map.getZoom())
return (
// ..LayersControl...
)
}
export default Layers
Однако, если бы мы хотели получать границы и уровень масштабирования каждый раз, когда они меняются, мы бы использовали хук useMapEvents. Мы импортируем его так же, как и хук useMap, но мы прикрепим обработчики событий карты Leaflet к экземпляру карты следующим образом:
Layers.jsx
import React from 'react'
// Import useMapEvents:
import { useMapEvents, TileLayer, LayersControl } from 'react-leaflet'
const Layers = () => {
// Call useMapEvents:
const map = useMapEvents({
// Use leaflet map event as the key and a call back with the
// map method as the value:
zoomend: () => {
// Get the zoom level once zoom ended:
console.log(map.getZoom())
},
moveend: () => {
// Get bounds once move has ended:
console.log(map.getBounds())
}
})
return (
// ...LayersControl...
)
}
export default Layers
Отображение данных с помощью GeoJSON
Очень высока вероятность, что в какой-то момент в процессе создания вашего картографического приложения вы будете получать и отображать данные в формате geoJSON. Наша карта в настоящее время сосредоточена на США, поэтому мы будем использовать геоданные для штатов Вайоминг, Монтана, а также Северная и Южная Дакота. Я уже настроил файлы, содержащие geoJSON для каждого состояния в src/data.
Чтобы отобразить geoJSON, мы собираемся использовать компонент слоя React-Leaflet GeoJSON. Мы собираемся импортировать данные Layers.jsx, поместить данные в массив в состоянии, затем использовать .map() для итерации этого массива и возврата слоев GeoJSON. При итерации данных нам необходимо передать свойство geometry, найденное в массиве features каждого набора geoJSON, которое дает слою GeoJSON тип и координаты создаваемого слоя. Нам также нужно будет предоставить уникальный ключ для каждого слоя GeoJSON, поэтому мы будем использовать display_name найденный в properties для каждого массива features. Если вы хотите изменить стиль слоя GeoJSON, вы можете передать объект опций в опору pathOptions. Вот как все это будет выглядеть:
Layers.jsx
import React, { useState } from 'react'
import { useMapEvents, TileLayer, LayersControl, GeoJSON } from 'react-leaflet'
import WY from '../data/Wyoming.json'
import MT from '../data/Montana.json'
import ND from '../data/NorthDakota.json'
import SD from '../data/SouthDakota.json'
const Layers = () => {
// Set all the border data to state array:
const [borderData, setBorderData] = useState([ND, MT, SD, WY])
const map = useMapEvents({
// ... Map Events ...
})
return (
<>
<LayersControl position="topright">
<LayersControl.BaseLayer checked name="Basic Map">
// ... LayersContol.BaseLayer ...
</LayersControl.BaseLayer>
{
// Iterate the borderData with .map():
borderData.map((data) => {
// Get the layer data from geojson:
const geojson = data.features[0].geometry
// Get the name of the state from geojson:
const state_name = data.features[0].properties.display_name
return (
// Pass data to layer via props:
<>
<GeoJSON key={state_name} data={geojson} pathOptions={{ color: 'blue' }} />
</>
)
})
}
</LayersControl>
</>
)
}
export default Layers
Добавление наложений в LayersControl
Чтобы добавить базовые слои к нашему LayersControl, мы использовали LayersControl.BaseLayer для каждого базового слоя, который мы хотели добавить на карту. Это очень похожий процесс добавления желаемых наложений. Вместо LayersControl.BaseLayer мы обернем наши слои в LayersControl.Overlay указав name и установив checked равным true чтобы слои отображались на карте по умолчанию:
Layers.jsx
import { useMapEvents, TileLayer, LayersControl, GeoJSON } from 'react-leaflet'
// ... Data Imports ...
const Layers = () => {
const [borderData, setBorderData] = useState([ND, MT, SD, WY])
const map = useMapEvents({
// ... Map Events ...
})
return (
<>
<LayersControl position="topright">
<LayersControl.BaseLayer checked name="Basic Map">
{// ... Layers Control: Base Layers ...}
</LayersControl.BaseLayer>
{borderData.map((data) => {
const geojson = data.features[0].geometry
const state_name = data.features[0].properties.display_name.split(',')[0]
// Wrap the geojson in LayersControl.Overlay. We'll use state_name
// as the name for the layer in the control and set checked to true:
return (
<>
<LayersControl.Overlay checked name={state_name}>
<GeoJSON key={state_name} data={geojson} pathOptions={{ color: 'blue' }} />
</LayersControl.Overlay>
</>
)
})}
</LayersControl>
</>
)
}
export default Layers
Добавление маркеров и всплывающих окон с LayerGroup
Допустим, мы хотим добавить больше в пользовательский интерфейс нашей карты, отображая некоторые маркеры, которые будут соответствовать geoJSON. Создать точки-маркеры невероятно просто. Мы просто импортируем компонент слоя React-Leaflet Marker, оборачиваем его компонентом слой Geojson и передаем объект latLng, который мы создадим с помощью метода Leaflet LatLng для его опоры position. Мы также импортируем компонент слоя Popup, добавим текст и обернем его компонентом Marker. Мы также можем использовать библиотеки, такие как Material UI, чтобы добавить дополнительный стиль к нашим всплывающим окнам. На данный момент мы просто будем использовать UI материала Typography и компоненты Divider:
Layers.jsx
import {
useMapEvents,
TileLayer,
LayersControl,
GeoJSON,
Marker, // Import the Marker and Popup layer components
Popup
} from 'react-leaflet'
// Import L from leaflet to create LatLng objects:
import L from 'leaflet'
// Import Material UI Components for styling:
import { Typography, Divider } from '@material-ui/core'
// ... Data Imports ...
const Layers = () => {
const [borderData, setBorderData] = useState([ND, MT, SD, WY])
const map = useMapEvents({
// ... Map Events ...
})
// Function to provide each state's latLng:
const getMarkerPosition = (state_name) => {
switch (state_name) {
case 'Montana':
// Use L.latLng to create latLng object.
// { "lat": LATITUDE, "lng": LONGITUDE }
return L.latLng(46.8797, -110.3626)
case 'Wyoming':
return L.latLng(43.0760, -107.2903)
case 'North Dakota':
return L.latLng(47.5515, -101.0020)
case 'South Dakota':
return L.latLng(43.9695, -99.9018)
default: return
}
}
return (
<>
<LayersControl position="topright">
<LayersControl.BaseLayer checked name="Basic Map">
{ // ... Base Layers ... }
</LayersControl.BaseLayer>
{borderData.map((data) => {
const geojson = data.features[0].geometry
const state_name = data.features[0].properties.display_name.split(',')[0]
// Wrap the Marker/Popup with the GeoJSON layer.
// Pass the getMarkerPosition to the position prop with the state_name param.
// Give the popup some Material UI styling with Typography and Divider:
return (
<>
<LayersControl.Overlay checked name={state_name}>
<GeoJSON key={state_name} data={geojson} pathOptions={{ color: 'blue' }}>
<Marker position={getMarkerPosition(state_name)}>
<Popup>
<Typography variant='subtitle2'>
{state_name}
</Typography>
<Divider />
<Typography variant='body2' style={{ margin: 3 }}>
Lat: {JSON.stringify(getMarkerPosition(state_name).lat)}
</Typography>
<Typography variant='body2' style={{ margin: 3 }}>
Lng: {JSON.stringify(getMarkerPosition(state_name).lng)}
</Typography>
</Popup>
</Marker>
</GeoJSON>
</LayersControl.Overlay>
</>
)
})}
</LayersControl>
</>
)
}
export default Layers
Обратите внимание на что-нибудь странное, особенно с LayersControl? Каждое имя отображается дважды. Это связано с тем, что LayersControl добавляет переключатель как для границы, так и для маркера точки с одним и тем же именем, чего мы не хотим. Чтобы исправить это, мы просто должны сказать, LayersControlчто компоненты GeoJson и Marker являются частью LayerGroup. Просто импортируйте компонент React-LeafletLayerGroup и используйте его как оболочку GeoJSON и Marker:
Layers.jsx
import {
useMapEvents,
TileLayer,
LayersControl,
LayerGroup, // Import LayerGroup
GeoJSON,
Marker,
Popup
} from 'react-leaflet'
// ... Imports ...
const Layers = () => {
const [borderData, setBorderData] = useState([ND, MT, SD, WY])
const map = useMapEvents({
// ... Map Events
})
const getMarkerPosition = (state_name) => {
// ... Marker Position ...
}
return (
<>
<LayersControl position="topright">
<LayersControl.BaseLayer checked name="Basic Map">
{ // ... Base Layers ... }
</LayersControl.BaseLayer>
{borderData.map((data) => {
console.log(data)
const geojson = data.features[0].geometry
const state_name = data.features[0].properties.display_name.split(',')[0]
// Wrap the GeoJSON component and its children with the LayerGroup component:
return (
<>
<LayersControl.Overlay checked name={state_name}>
<LayerGroup>
<GeoJSON key={state_name} data={geojson} pathOptions={{ color: 'blue' }}>
<Marker position={getMarkerPosition(state_name)}>
<Popup>
{ // ... Popup Content ... }
</Popup>
</Marker>
</GeoJSON>
</LayerGroup>
</LayersControl.Overlay>
</>
)
})}
</LayersControl>
</>
)
}
export default Layers
Обработчики событий слоя
Бывают случаи, когда мы захотим изменить элементы на нашей карте, например, изменить fillOpacity для GeoJSONс событием onmouseover и снова onmouseout. Чтобы добавить эту функциональность, мы будем использовать опору eventHandlers для GeoJSON. Многие компоненты React-Leaflet имеют опору eventHandlers, но некоторые нет, поэтому обязательно обратитесь к документации. Для обработки событий наведения и вывода мыши мы настроим функцию с оператором switch, которая обрабатывает оба случая:
Layers.jsx
// ... Imports ...
const Layers = () => {
const [borderData, setBorderData] = useState([ND, MT, SD, WY])
const map = useMapEvents({
// ... Map Events ...
})
const getMarkerPosition = (state_name) => {
// ... Marker Position ...
}
// Our mouse event handler:
const onMouseEvent = (event, type) => {
switch (type) {
case 'over':
// Set the style of the Leaflet DOM element:
event.target.setStyle({ fillOpacity: 0.5 })
break
case 'out':
event.target.setStyle({ fillOpacity: 0.0 })
break
default:
break
}
}
return (
<>
<LayersControl position="topright">
<LayersControl.BaseLayer checked name="Basic Map">
{// ... Base Layers ... }
</LayersControl.BaseLayer>
{borderData.map((data) => {
const geojson = data.features[0].geometry
const state_name = data.features[0].properties.display_name.split(',')[0]
// We use the eventHandlers prop to tell the GeoJSON layer to listen for mouse events:
return (
<>
<LayersControl.Overlay checked name={state_name}>
<LayerGroup>
<GeoJSON
key={state_name}
data={geojson}
pathOptions={{ color: 'blue' }}
eventHandlers={{
mouseover: (event, type) => onMouseEvent(event, 'over'),
mouseout: (event, type) => onMouseEvent(event, 'out'),
}}
>
<Marker position={getMarkerPosition(state_name)}>
<Popup>
{// ... Popup Content ... }
</Popup>
</Marker>
</GeoJSON>
</LayerGroup>
</LayersControl.Overlay>
</>
)
})}
</LayersControl>
</>
)
}
export default Layers
В завершение
Хорошо, теперь у нас есть работающее картографическое приложение, созданное с помощью React-Leaflet версии 3! Вот финальная версия нашего кода:
Layers.jsx
import React, { useState } from 'react'
import {
useMapEvents,
TileLayer,
LayersControl,
LayerGroup,
GeoJSON,
Marker,
Popup,
} from 'react-leaflet'
import L from 'leaflet'
import { Typography, Divider } from '@material-ui/core'
import WY from '../data/Wyoming.json'
import MT from '../data/Montana.json'
import ND from '../data/NorthDakota.json'
import SD from '../data/SouthDakota.json'
const Layers = () => {
const [borderData, setBorderData] = useState([ND, MT, SD, WY])
const map = useMapEvents({
zoomend: () => {
console.log(map.getZoom())
},
moveend: () => {
console.log(map.getBounds())
},
})
const getMarkerPosition = (state_name) => {
switch (state_name) {
case 'Montana':
return L.latLng(46.8797, -110.3626)
case 'Wyoming':
return L.latLng(43.076, -107.2903)
case 'North Dakota':
return L.latLng(47.5515, -101.002)
case 'South Dakota':
return L.latLng(43.9695, -99.9018)
default:
return
}
}
const onMouseEvent = (event, type) => {
switch (type) {
case 'over':
event.target.setStyle({ fillOpacity: 0.5 })
break
case 'out':
event.target.setStyle({ fillOpacity: 0.0 })
break
default:
break
}
}
return (
<>
<LayersControl position='topright'>
<LayersControl.BaseLayer checked name='Basic Map'>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
/>
</LayersControl.BaseLayer>
<LayersControl.BaseLayer name='Topo Map'>
<TileLayer
attribution='Map data: © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: © <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
url='https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png'
/>
</LayersControl.BaseLayer>
{borderData.map((data) => {
const geojson = data.features[0].geometry
const state_name = data.features[0].properties.display_name.split(
','
)[0]
return (
<>
<LayersControl.Overlay checked name={state_name}>
<LayerGroup>
<GeoJSON
key={state_name}
data={geojson}
pathOptions={{ color: 'blue', fillOpacity: 0 }}
eventHandlers={{
mouseover: (event, type) => onMouseEvent(event, 'over'),
mouseout: (event, type) => onMouseEvent(event, 'out'),
}}
>
<Marker position={getMarkerPosition(state_name)}>
<Popup>
<Typography variant='subtitle2'>
{state_name}
</Typography>
<Divider />
<Typography variant='body2' style={{ margin: 3 }}>
Lat:{' '}
{JSON.stringify(getMarkerPosition(state_name).lat)}
</Typography>
<Typography variant='body2' style={{ margin: 3 }}>
Lng:{' '}
{JSON.stringify(getMarkerPosition(state_name).lng)}
</Typography>
</Popup>
</Marker>
</GeoJSON>
</LayerGroup>
</LayersControl.Overlay>
</>
)
})}
</LayersControl>
</>
)
}
export default Layers
Map.jsx
import React from 'react'
import { MapContainer, ZoomControl } from 'react-leaflet'
import Layers from './Layers'
const Map = () => {
return (
<>
<MapContainer
center={[37.0902, -95.7129]}
zoom={3}
zoomControl={false}
style={{ height: '100vh', width: '100%' }}
>
<Layers />
<ZoomControl position='topright' />
</MapContainer>
</>
)
}
export default Map
Я рекомендую вам прочитать документацию, так как с этим пакетом вы можете сделать множество интересных вещей.
После того, как вы попрактикуетесь в использовании всех хуков и компонентов, которые может предложить общедоступный API React-Leaflet, перейдите в раздел документации Core API. Core API позволяет создавать настраиваемые компоненты Leaflet и расширять сторонние плагины Leaflet для работы с React-Leaflet.