В этом примере проекта мы используемLeaflet, легкую картографическую библиотеку с открытым исходным кодом и базовый слой карты из OpenStreetMap для создания карта внутри приложения React. Данные geoJSON, которые мы используем для добавления дополнительного слоя, извлекаются из cartodb.
Демонстрационную карту листовки реакции можно посмотреть здесь.
Мы используем такие зависимости, как useRef, useEffect от реакции. И библиотека javascript листовки и css. Сначала нам нужно создать реагирующее приложение с помощью команды create-react-app.
Установка
npx create-react-app <app_name> cd <app_name> npm start
npm start
запустит сервер разработки, и в браузере откроется приложение по умолчанию. Далее нам нужно установить зависимости, в данном случае только библиотеку листовок. В папке src приложения введите команду установки npm вместе с именем пакета в качестве аргумента в командной строке/терминале.
npm install leaflet
Создание карты внутри компонента приложения
В файле App.js, который находится в папке src, импортируйте все зависимости, необходимые для проекта.
import { useRef, useEffect } from 'react'; import '../../../node_modules/leaflet/dist/leaflet.css'; import L from 'leaflet';
Компонент приложения()
Внутри компонента приложения, который возвращает контейнер карты, <div id="map_container" ref={map_container_ref}></div>
будет содержать карту после ее инициализации. Переменная map_container_ref
const содержит ссылку на контейнер карты.
const App = () => { const map_container_ref = useRef(null); const display_map = () => { // ... } useEffect(() => { const map_instance = display_map(); /* clean up return () => { if (map_instance._loaded) { map_instance.remove(); } }; }, []); return ( <div id="map_container" ref={map_container_ref}></div> ); }
После того, как React обновил DOM, мы используем хук react useEffect для инициализации карты с помощью функции display_map(); который возвращает экземпляр созданной карты. Мы можем использовать эту ссылку, чтобы уничтожить карту и очистить все связанные прослушиватели событий в разделе очистки хука useEffect.
useEffect(() => { const map_instance = display_map(); // clean up return () => { if (map_instance._loaded) { map_instance.remove(); } }; }, []);
Показать карту
Внутри display_map()
на контейнер карты можно ссылаться с помощью map_container_ref
. С помощью этой ссылки мы можем создать базовый слой тайлов.
/* * Creating map */ const display_map = () => { const id = map_container_ref.current.id; const latitude = 0; const longitude = 0; const zoom = 2; const tile = "https://tile.openstreetmap.be/osmbe/{z}/{x}/{y}.png"; const attribution = '© <a href="http://openstreetmap.org">OpenStreetMap</a> contributors' + ', Tiles courtesy of <a href="https://geo6.be/">GEO-6</a>'; const map = L.map(id).setView([latitude, longitude], zoom); L.tileLayer(tile, { attribution: attribution, maxZoom: 18, }).addTo(map); return map; };
Добавьте немного стиля
/*Inside App.css*/ #map_container { height: 450px; }
Это отобразит карту с тайлами из OpenStreetMap. Также не забудьте добавить свойство height в контейнер карты в файле App.css.
Отображение базового слоя
Код до этого момента создает карту с базовым слоем
/* * Code up to this point */ import { useRef, useEffect } from "react"; import "../../../node_modules/leaflet/dist/leaflet.css"; import L from "leaflet"; const App= () => { const map_container_ref = useRef(null); const display_map = () => { const id = map_container_ref.current.id; const latitude = 0; const longitude = 0; const zoom = 2; const tile = "https://tile.openstreetmap.be/osmbe/{z}/{x}/{y}.png"; const attribution = '© <a href="http://openstreetmap.org">OpenStreetMap</a> contributors' + ', Tiles courtesy of <a href="https://geo6.be/">GEO-6</a>'; const map = L.map(id).setView([latitude, longitude], zoom); L.tileLayer(tile, { attribution: attribution, maxZoom: 18, }).addTo(map); return map; }; useEffect(() => { const map_instance = display_map(); // clean up return () => { if (map_instance._loaded) { map_instance.remove(); } }; }, []); return ( <div id="map_container" ref={map_container_ref}></div> ); }; export default App;
Показать геоJSON
Далее мы собираемся добавить слой geoJSON из cartodb поверх нашей карты, используя метод L.geoJSON()
листовки. Создайте функцию, скажем, display_population_tile()
и вызовите ее после добавления базового слоя.
/* * Fetch the data and if it's not null display it on the map with pop. */ const display_population_tile = (map) => { const url = "https://cartovl.carto.com/api/v2/sql?q=SELECT%20*%20FROM%20populated_places_small&format=GeoJSON"; fetch_geoJSON(url) .then((geojson_data) => { if (geojson_data) { L.geoJSON(geojson_data, { pointToLayer: function (feature, latlng) { return L.circleMarker(latlng, { radius: 8, fillColor: "#ef4b38", color: "#000", weight: 0.5, opacity: 1, fillOpacity: 1, }); }, onEachFeature: onEachFeaturePoint, }).addTo(map); } }).catch((e) => console.error(e)); };
Получить данные
const fetch_geoJSON = async (url) => { const response = await fetch(url); if (response.status >= 200 && response.status <= 299) { const data = await response.json(); return data; } return null; };
Функция onEachFeaturePoint()
связывает содержимое всплывающего окна
const onEachFeaturePoint = (feature, layer) => { let popupContent = ""; if (feature.properties && feature.properties.adm0name) { popupContent += "<h4>Country: " + feature.properties.adm0name + "</h4>"; } if (feature.properties && feature.properties.adm1name) { popupContent += "<h5>City: " + feature.properties.adm1name + "</h5>"; } layer.bindPopup(popupContent); };
Весь код этого проекта
/* * Display a base map from OpenStreetMap with Leaflet * Add a geoJSON layer */ import { useRef, useEffect } from "react"; import "../../../node_modules/leaflet/dist/leaflet.css"; import L from "leaflet"; const App= () => { const map_container_ref = useRef(null); // Fetch the geoJSON sample data from cartodb const fetch_geoJSON = async (url) => { const response = await fetch(url); if (response.status >= 200 && response.status <= 299) { const data = await response.json(); return data; } return null; }; // Display popup when clicked on the geoJSON layer with info const onEachFeaturePoint = (feature, layer) => { let popupContent = ""; if (feature.properties && feature.properties.adm0name) { popupContent += "<h4>Country: " + feature.properties.adm0name + "</h4>"; } if (feature.properties && feature.properties.adm1name) { popupContent += "<h5>City: " + feature.properties.adm1name + "</h5>"; } layer.bindPopup(popupContent); }; // Display the geoJSON on map const display_population_tile = (map) => { const url = "https://cartovl.carto.com/api/v2/sql?q=SELECT%20*%20FROM%20populated_places_small&format=GeoJSON"; fetch_geoJSON(url) .then((geojson_data) => { if (geojson_data) { L.geoJSON(geojson_data, { pointToLayer: function (feature, latlng) { return L.circleMarker(latlng, { radius: 8, fillColor: "#ef4b38", color: "#000", weight: 0.5, opacity: 1, fillOpacity: 1, }); }, onEachFeature: onEachFeaturePoint, }).addTo(map); } }).catch((e) => console.error(e)); }; //Display the base layer const display_map = () => { const id = map_container_ref.current.id; const latitude = 0; const longitude = 0; const zoom = 2; const tile = "https://tile.openstreetmap.be/osmbe/{z}/{x}/{y}.png"; const attribution = '© <a href="http://openstreetmap.org">OpenStreetMap</a> contributors' + ', Tiles courtesy of <a href="https://geo6.be/">GEO-6</a>'; const map = L.map(id).setView([latitude, longitude], zoom); L.tileLayer(tile, { attribution: attribution, maxZoom: 18, }).addTo(map); display_population_tile(map); return map; }; useEffect(() => { const map_instance = display_map(); // clean up return () => { if (map_instance._loaded) { map_instance.remove(); } }; }, []); return ( <div id="map_container" ref={map_container_ref}></div> ); }; export default App;
Подведение итогов
В этом посте мы рассмотрим только некоторые основы листовки и реакции. С помощью Leaflet и React мы можем создавать более сложные карты. Надеюсь, вам понравилась моя первая статья. Если вы нашли это полезным, то я благодарен. Если вы обнаружили некоторые проблемы, пожалуйста, прокомментируйте. Также приветствуются критические замечания и предложения.