В этом блоге вы узнаете, как получить приблизительные координаты пользователя и отметить их на карте GoogleMapReact.

Обзор шага:

  • Получите Ключ API Google.
  • Получите координаты пользователя. В этом блоге представлены два разных способа достижения этой цели. Вариант 1 использует встроенную геолокацию Google Chrome, а вариант 2 использует API геокодирования Google (для браузеров, которые могут не поддерживать первый подход, или для пользователей, которые решили не обрабатывать свое местоположение через браузер.)
  • Добавьте Geocoding AP I в список API вашего проекта. Этот API позволит вам получать координаты пользователя путем преобразования адреса или города и штата (как минимум) в приблизительные координаты широты и долготы.
  • Установите google-map-react »
  • Визуализируйте карту с маркером местоположения пользователя.

В руководстве будут фрагменты кода, а код, удобный для копирования и вставки, находится в конце. 🔥

Вариант 1. Использование метода геолокации Google Chrome:

Первое, что вам нужно знать, это то, что местоположение может быть определено браузером только после пользовательского события. Это означает, что вам нужно активировать эту функцию после того, как пользователь разрешил браузеру это сделать. В этом примере мы будем делать это с помощью onClick кнопки в простой форме.

Кнопка «Текущее местоположение» имеет следующий прослушиватель событий

onClick={() => getPosition()}

Первая функция цепочки событий следующая:

Эта функция использует navigator.geolocation.getCurrentPosition для обработки вашего местоположения. Он принимает функцию обратного вызова успеха, функцию обратного вызова ошибки и параметр параметров (который я решил не использовать). Обратные вызовы успеха и ошибки приведены ниже.

Функция convertToAddress не является обязательной и включена ниже. Эта функция будет использовать ключ API Google для преобразования ваших координат широты и долготы в город, штат и почтовый индекс. Он использует ключ Google API и Google Geocoding API. Для этого примера я получил ключ API из серверной части.

На этом этапе у вас должен быть доступ к координатам широты и долготы через Google Chrome.

Что делать, если у вас нет доступа к координатам широты и долготы из-за того, что пользователь решил не сообщать свое местоположение браузеру или браузер не поддерживает обработку геолокации? Вариант 2.

Вариант 2. Использование API геокодирования Google:

Мы будем использовать город и штат, введенные пользователем в форму ниже, чтобы преобразовать их в координаты широты и долготы при отправке формы.

Кнопка «Отправить местоположение» имеет следующий прослушиватель событий

onClick={() => processManualLocation()}

Первая функция цепочки событий следующая:

Эта функция использует ручные записи города и штата вместе с ключом Google API, хранящимся в файле .env во внешнем интерфейсе. Вы можете включить полный адрес в URL-адрес для получения, и местоположение ответа Google Geocoding будет более точным. Для этого конкретного случая использования города и штата будет достаточно. Если статус ответа API геокодирования Google - ОК, эта функция вызывает следующую функцию в цепочке:

После запуска последней функции в цепочке у вас должен быть доступ к приблизительным координатам широты и долготы пользователя.

Теперь, когда у нас есть координаты пользователей, давайте сопоставим их на Google Maps в вашем приложении React-Redux. Я решил использовать "google-map-react".

Создание карты "google-map-react" с пользовательским маркером:

После того, как вы установили google-map-react и получили доступ к координатам пользователя, вам нужно будет написать следующий код (или аналогичный):

Я не комментировал эту часть кода, поскольку знания, необходимые для ее понимания, являются базовыми React-Redux.

Вот как должна выглядеть карта:

Надеюсь, вам понравился этот урок. Дайте знать, если у вас появятся вопросы!

Код, удобный для копирования и вставки, с комментариями:

Получение широты / долготы, города, штата и почтового индекса из геолокации Google Chrome:

// If browser supports navigator.geolocation, generate Lat/Long else let user know there is an error
const getPosition = () => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition, posError); // Passing in a success callback and an error callback fn
} else {
alert("Sorry, Geolocation is not supported by this browser."); // Alert is browser does not support geolocation
}
}
// Geolocation error callback fn. Query permissions to check if the error occured due to user not allowing location to be shared
const posError = () => {
if (navigator.permissions) {
navigator.permissions.query({ name: 'geolocation' }).then(res => {
if (res.state === 'denied') {
alert('Enable location permissions for this website in your browser settings.')
}
})
} else {
alert('Unable to access your location. You can continue by submitting location manually.') // Obtaining Lat/long from address necessary
}
}
// Geolocation success callback fn
const showPosition = (position) => {
let lat = position.coords.latitude // You have obtained latitude coordinate!
let long = position.coords.longitude // You have obtained longitude coordinate!
props.set_lat(lat) // Using dispatch to modify lat store state
props.set_long(long) // Using dispatch to modify long store state
convertToAddress(lat, long) // Will convert lat/long to City, State, & Zip code
}
// Fetching for google API key from back-end (Optional, you can store it in .env file in front-end)
const convertToAddress = (lat, long) => {
fetch('http://localhost:3000/googlemaps')
.then(res => res.json())
.then(obj => getAddress(lat, long, obj.api_key))
}
// Converting lat/long from browser geolocation into city, state, and zip code using Google Geocoding API
const getAddress = (lat, long, googleKey) => {
fetch(`https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${long}&key=${googleKey}`)
.then(res => res.json())
.then(address => setZip(address))
}
// Dispatching city, state, and zip code to store state
const setZip = (address) => {
let city = address.results[5].address_components[2].short_name
let state = address.results[5].address_components[4].short_name
let postal = address.results[5].address_components[0].short_name
props.set_city(city)
props.set_state(state)
props.set_postal_code(postal)
}

Преобразование введенных вручную городов и штатов в широту и долготу:

// Function that will convert city & state to approximate user lat/long coordinates from manual entry
const processManualLocation = () => {
if (props.userState !== "" && props.userCity !== "") {
let city = props.userCity // manual lat entry is already in store state
let state = props.userPostalCode // manual long entry is already in store state
// This fetch uses the API key stored in your fron-end .env file "process.env.REACT_APP_googleKey"
let url = `https://maps.googleapis.com/maps/api/geocode/json?address=+${city},+${state}&key=${process.env.REACT_APP_googleKey}`
fetch(url)
.then(res => res.json())
.then(res => {
if (res.status === "OK") {
getUserCoords(res.results)
} else if (res.status === "ZERO_RESULTS") {
alert('Unable to process this location. Please revise location fields and try submitting again.')
}
})
} else {
alert('Please ensure State and City are provided.')
}
}
// Obtaining and dispatching lat and long coords from google geocoding API response
const getUserCoords = (googleRes) => {
let lat = googleRes[0].geometry.location.lat // You have obtained latitude coordinate!
let long = googleRes[0].geometry.location.lng // You have obtained longitude coordinate!
props.set_lat(lat) // dispatching to store state
props.set_long(long) //dispatching to store state
}

Полный код "google-map-react":

import React from 'react';
import { connect } from "react-redux";
import GoogleMapReact from 'google-map-react';
const UserMap = (props) => {
let userInfo = {
center: {
lat: props.userLat,
lng: props.userLong
},
zoom: 10
};
const renderMarker = (map, maps) => {
let marker = new maps.Marker({
position: userInfo.center,
map,
title: "User Location"
});
return marker;
};
return (
<div className="user-map" style={{ height: '600px', width: '600px' }}>
<GoogleMapReact
bootstrapURLKeys={{ key: process.env.REACT_APP_googleKey }} // My Google API is stored in the .env file in front-end
defaultCenter={userInfo.center}
defaultZoom={userInfo.zoom}
yesIWantToUseGoogleMapApiInternals={true}
onGoogleApiLoaded={({ map, maps }) => {
renderMarker(map, maps)
}}
>
</GoogleMapReact>
</div>
);
}
const mapStateToProps = (state) => {
return {
userLat: state.userState.userLat,
userLong: state.userState.userLong,
}
}
export default connect(mapStateToProps)(UserMap);