Второй раздел моего свадебного веб-сайта предназначен для отображения всей информации, связанной с местом проведения свадьбы: где будет проходить церемония, как туда добраться, а также некоторые предложения, где остановиться.
Это статический компонент, поскольку вся необходимая информация жестко закодирована. Основной план включает в себя несколько фотографий местности, описание места и способы добраться до него. Чтобы улучшить свои навыки React, что является основной причиной, по которой я работаю над этим проектом, я решил включить Google Maps в этот раздел. Это сделано для визуального отображения основных мест проведения свадьбы на интерактивной карте.
Реализовать эту функцию можно разными способами:
- просто добавив снимок экрана или встроенную карту Google
- используя пакет, который предоставляет предварительно разработанный компонент React для отображения карты
- работаю с API Карт Google для создания собственного компонента карты.
Встроенная карта не обеспечивала тот тип интерактивности, который я хотел для моих пользователей, а компонент React не давал мне слишком большой гибкости в отношении стиля. Фактически, готовый компонент поставляется уже завернутым в div с абсолютным позиционированием, и я не смог найти способ стилизовать этот внешний div (, если вы когда-либо использовали google-react-maps, а вы знаете, как вносить изменения в оболочку, обращайтесь).
С помощью документации Google Maps API и видеоурока от Yahya Elharony я смог создать свой собственный компонент Карта с серией маркеров с собственным информационным окном. Местоположение хранится в состоянии компонента, так как в будущем я мог бы разрешить пользователям добавлять свои собственные местоположения на карту.
Документация по API Карт предельно ясна, но написана для JavaScript, а не React. Самым сложным было понять, как загрузить Maps JavaScript API в приложение React. В простом приложении JavaScript мы бы добавили тег скрипта и его содержимое непосредственно перед закрывающим тегом body в файле HTML, однако как это работает в проекте React? Решение состоит в том, чтобы создать функцию, которая генерирует скрипт для загрузки API Карт, а затем вызывать ее из нашего компонента Карты.
Это тег скрипта, представленный в Руководстве по Maps JavaScript:
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"
async defer></script>
В нашем файле Map.js вне компонента, но до объявления экспорта по умолчанию, мы создаем функцию с именем loadScript, которая принимает URL-адрес в качестве единственного параметра. Первая строка этой функции сохранит первый тег скрипта нашего документа в переменную с именем index. Строки 3–6 создадут сценарий, описанный Maps JavaScript API, а последняя строка вставит наш сценарий перед сценарием индекса в его родительском узле. Это сохранит наш сценарий в самом начале нашего списка сценариев.
function loadScript(url) {
var index = window.document.getElementsByTagName(“script”)[0];
var script = window.document.createElement(“script”);
script.src = url;
script.async = true;
script.defer = true;
index.parentNode.insertBefore(script, index);
}
Затем мы вызываем эту функцию из нашего компонента и передаем URL-адрес, заполненный нашим ключом API, в качестве параметра. Это полный код для простого компонента Map, в котором я также создал стиль const для управления стилем карты (позже я решил переместить стиль в отдельный файл Map.css, так как я также хотел стилизовать информационные окна) .

Теперь давайте добавим маркеры в собственное информационное окно. Как уже упоминалось, на данный момент местоположения жестко запрограммированы и хранятся в массиве с именем mapLocation в состоянии компонента Map.
Внутри функции initMap () мы пройдемся по локациям в состоянии и создадим маркер для каждого из них с помощью конструктора google.maps.Marker.
this.state.mapLocations.map(location => {
const marker = new window.google.maps.Marker({
position: {
lat: location.position.lat,
lng: location.position.lng
},
map: map,
title: location.title
});
});
Следующим шагом является создание информационного окна для каждого из местоположений, в котором будет отображаться ряд информации. Мы можем определить, какой контент будет отображаться в переменной contentString, которую мы создадим внутри цикла. Например, в моем случае я включил название места, краткое описание и изображение. Затем я применил стиль для информационного окна в файле Map.css. Информационное окно не появится, если мы не свяжем его с маркером через событие щелчка: только при щелчке по маркеру откроется информационное окно.
this.state.mapLocations.map(location => {
const infowindow = new window.google.maps.InfoWindow(
content: contentString);
const contentString = `<div class="container">
<h2>${location.name}</h2>
<p>${location.description}</p>
<img src="${location.image}" /></div>`;
const marker = new window.google.maps.Marker({
position: {
lat: location.position.lat,
lng: location.position.lng
},
map: map,
title: location.title
});
marker.addListener("click", function() {
infowindow.open(map, marker);
});
});
Однако этот код представляет небольшую проблему: все информационные окна останутся открытыми, если мы не нажмем крестик в правом верхнем углу всплывающего окна, чтобы закрыть каждое из них. Чтобы решить эту проблему, мы можем переместить информационное окно const за пределы цикла после удаления его содержимого, а затем мы можем добавить следующую функцию в функцию прослушивателя событий, которую мы объявили в нижней части нашего цикла:
marker.addListener("click", function() {
infowindow.setContent(contentString);
infowindow.open(map, marker);
});
});
Окончательный код для компонента карты здесь, включая маркеры и информационные окна:
Вот так страница выглядит на данный момент. Следующим шагом будет работа над формой RSVP и ее интеграция с Firebase.
Ресурсы, используемые для этого раздела сайта:
Учебник по Google Maps API - очень полезная документация по Google Maps API. Я снова воспользуюсь этой страницей для изменения значков на карте.
Youtube-учебник от Yahya Elharony - Реализация API Карт Google очень четко объясняется в этом видео-руководстве (5 частей).