Введение в React Native Maps
Наличие точной информации о местоположении ваших пользователей — отличный способ улучшить взаимодействие с пользователем. Например, вы можете использовать эти данные, чтобы показывать пользователям, что их окружает, предлагать эксклюзивные предложения для продуктов и услуг в их регионе и многое другое.
К счастью, если у вас есть приложение React, реализовать карты с помощью react-native-maps
библиотеки не составит труда .
Что такое React Native Maps?
React Native Maps — это система компонентов для карт, которая поставляется с собственным кодом платформы, который необходимо скомпилировать вместе с React Native. В этом руководстве мы покажем, как интегрировать Карты Google в ваше приложение React Native, и познакомим вас с основными компонентами, такими как <MapView />
и <Marker>
.
Давайте начнем!
Настройка
Перед визуализацией нашего MapView
компонента нам сначала нужно получить ключ API, чтобы включить функции Google Maps в наше приложение. Для этого получите секреты ключ API, выполнив следующие действия .
<application> <!-- You will only need to add this meta-data tag, but make sure it's a child of application --> <meta-data android:name="com.google.android.geo.API_KEY" android:value="YOUR_API_KEY"/> <!-- Your key goes here. --> <!-- You will also only need to add this uses-library tag --> <uses-library android:name="org.apache.http.legacy" android:required="false"/> </application>
Это подключит наш ключ SDK к проекту React Native .
Затем выполните следующую команду для установки react-native-maps
в свой проект.
yarn add react-native-maps -E npm install react-native-maps #Expo requires a different version of this package. # so if you are using Expo, run this instead: expo install react-native-maps
Настройка вида карты по умолчанию
Удалите весь код по умолчанию из App.js
файла и импортируйте <MapView />
компонент из react-native-maps
. Внутри компонента визуализируйте <MapView />
компонент.
import React from "react"; import { StyleSheet, Text, View } from "react-native"; import MapView from "react-native-maps"; export default function App() { return ( <View style={styles.container}> {/*Render our MapView*/} <MapView style={styles.map} //specify our coordinates. initialRegion={{ latitude: 37.78825, longitude: -122.4324, latitudeDelta: 0.0922, longitudeDelta: 0.0421, }} /> </View> ); } //create our styling code: const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, flex: 1, //the container will fill the whole screen. justifyContent: "flex-end", alignItems: "center", }, map: { ...StyleSheet.absoluteFillObject, }, });
Свойство initialRegion
показывает регион, который должен отображаться на карте при монтировании компонента. Значение initialRegion
не может быть изменено после инициализации.
Не забудьте добавить свойство стиля, чтобы указать размеры; в противном случае вы получите белый экран. Значение гарантирует, что занимает весь экран.{ flex: 1 }<MapView />
Вам нужно будет передать объект со значениями широты, долготы и дельты региона в свойство initialRegion
. Свойства latitudeDelta
и longitudeDelta
определяют, насколько область на карте должна быть увеличена. Для смены региона используйте region
prop.
Использование React Native Maps с useState
хуком
Чтобы изменить регион с помощью useState
Hook, используйте onRegionChangeComplete
prop, чтобы установить новый регион в состояние. Это onRegionChangeComplete
prop обратного вызова, который запускается, когда пользователь прекращает панорамирование карты.
//extra code removed for brevity. //create a Hook to store our region data. const [region, setRegion] = useState({ latitude: 51.5079145, longitude: -0.0899163, latitudeDelta: 0.01, longitudeDelta: 0.01, }); return ( <View style={styles.container}> <MapView style={styles.map} initialRegion={{ latitude: 37.78825, longitude: -122.4324, latitudeDelta: 0.0922, longitudeDelta: 0.0421, }} //onRegionChangeComplete runs when the user stops dragging MapView onRegionChangeComplete={(region) => setRegion(region)} /> {/*Display user's current region:*/} <Text style={styles.text}>Current latitude: {region.latitude}</Text> <Text style={styles.text}>Current longitude: {region.longitude}</Text> </View> ); }} // onRegionChangeComplete запускается , когда пользователь перестает перетаскивать MapView onRegionChangeComplete = {( регион ) => setRegion(регион)} /> { /*Показать текущий регион пользователя:*/ } < Стиль текста = { стили . text } > Текущая широта : { region . широта } </ Text > < Стиль текста = { стили . text } > Текущая долгота : { region . долгота } </ Text > </ Просмотр > );
Добавление маркера
Начните с импорта Marker
из .react-native-maps
import { Marker } from "react-native-maps";
Затем визуализируйте компонент как дочерний элемент . Передайте координату маркера в реквизите.<Marker /><MapView />coordinate
import { Marker } from "react-native-maps"; const tokyoRegion = { latitude: 35.6762, longitude: 139.6503, latitudeDelta: 0.01, longitudeDelta: 0.01, }; return ( <View style={styles.container}> <MapView style={styles.map} initialRegion={tokyoRegion} //your region data goes here. > {/*Make sure the Marker component is a child of MapView. Otherwise it won't render*/} <Marker coordinate={tokyoRegion} /> </MapView> </View> );
Теперь маркер должен быть виден, как показано ниже.
Вы можете добавить n
несколько маркеров на карту и передать ее как прямой дочерний элемент компоненту .<MapView />
Вот пример нескольких Marker
компонентов в одном MapView
:
<MapView ref={mapRef} style={styles.map} initialRegion={tokyoRegion} onRegionChangeComplete={(region) => setRegion(region)} > <Marker coordinate={tokyoRegion} /> {/*marker to a nearby location */} <Marker coordinate={{ latitude: 35.67714827145542, longitude: 139.6551462687416, }} /> </MapView>;
Настройка маркера карты
Изменение цвета
Чтобы изменить цвет маркера, используйте реквизит pinColor
.
<Marker coordinate={tokyoRegion} pinColor="green" />
Здесь мы меняем цвет булавки на green
:
Изменение изображения маркера
Вы также можете добавить собственное изображение маркера, передав image
свойство компоненту .<Marker />
<Marker coordinate={{ latitude: 52.5200066, longitude: 13.404954 }} image={require("./japaneseFlag.png")} //uses relative file path. />
Изменение вида маркера
react-native-maps
также позволяет разработчикам использовать настраиваемые представления маркеров. Это может быть полезно в ситуациях, когда вы хотите указать местоположение с помощью символа. Примером может быть отображение Car
компонента для отображения позиции продавца автомобилей.
Для этого сначала начните с написания кода для создания пользовательского компонента, например:
//create our custom marker component. function CustomMarker() { return ( <View style={styles.marker}> <Text style={styles.color}>Tokyo</Text> </View> ); } //styles for our custom marker. const styles = StyleSheet.create({ marker: { paddingVertical: 10, paddingHorizontal: 30, backgroundColor: "#007bff", borderColor: "#eee", borderRadius: 5, elevation: 10, }, text: { color: "#fff", }, });
Затем включите CustomMarker
в свой проект.
export default function App() { return ( <View style={styles.container}> <MapView style={styles.map} initialRegion={tokyoRegion}> <Marker coordinate={tokyoRegion}> {/* CustomMarker has to be a child of Marker*/} <CustomMarker /> </Marker> </MapView> </View> ); }
Стилизация карты
Создайте объект JSON, который вы будете использовать для разработки карты, с помощью генератора стилей Google . Затем передайте сгенерированный объект стиля в prop customMapStyle
компонента .<MapView />
import React, { useState, useRef } from "react"; import { StyleSheet, Text, View, Button } from "react-native"; import MapView, { Marker } from "react-native-maps"; const mapStyle = []; //map styles go here! export default function App() { return ( <View style={styles.container}> <MapView style={styles.map} initialRegion={tokyoRegion} customMapStyle={mapStyle} //plug in our custom style into the customMapStyle prop. /> </View> ); }
Вы можете игнорировать mapStyle
переменную — поскольку мы генерируем стиль карты с помощью генератора, вам нужно только вставить сгенерированный объект JSON в свой код и отправить его компоненту .<MapView />
Как видите, стиль карты изменился со светлой темы по умолчанию на темную тему.
Получение текущего местоположения или конкретной координаты
Что делать, если вы хотите анимировать по определенной координате?
Сначала создайте ссылку на использование хука:<MapView />useRef()
import { useRef } from "react"; const mapRef = useRef(null); <MapView ref={mapRef} //assign our ref to this MapView /*further code.. */ />
Это означает, что теперь мы можем выполнять методы для управления нашим MapView
компонентом.
Затем добавьте этот блок:
//extra code removed for brevity //destination coordinates const tokyoRegion = { latitude: 35.6762, longitude: 139.6503, latitudeDelta: 0.01, longitudeDelta: 0.01, }; const goToTokyo = () => { //Animate the user to new region. Complete this animation in 3 seconds mapRef.current.animateToRegion(tokyoRegion, 3 * 1000); }; return ( <View style={styles.container}> <Button onPress={() => goToTokyo()} title="Go to Tokyo" /> </View> );
Вот разбивка этого фрагмента:
Хук возвращает изменяемый объект ref, свойство которого имеет значение переданного аргумента. Если значение свойства равно , это означает, что компонент еще не смонтирован. Теперь вы можете получить доступ к любому из методов, используя .useRef()currentcurrentundefined<MapView />mapRef.current
Метод принимает любые два параметра: координаты пункта назначения (в данном случае ) и продолжительность анимации в миллисекундах.animateToRegion()tokyoRegion
В итоге код в вашем файле должен выглядеть так:App.js
export default function App() { const mapRef = useRef(null); const [region, setRegion] = useState({ latitude: 51.5079145, longitude: -0.0899163, latitudeDelta: 0.01, longitudeDelta: 0.01, }); const tokyoRegion = { latitude: 35.6762, longitude: 139.6503, latitudeDelta: 0.01, longitudeDelta: 0.01, }; const goToTokyo = () => { //complete this animation in 3 seconds mapRef.current.animateToRegion(tokyoRegion, 3 * 1000); }; return ( <View style={styles.container}> <MapView ref={mapRef} style={styles.map} initialRegion={{ latitude: 24.8607, longitude: 67.0011, latitudeDelta: 0.0922, longitudeDelta: 0.0421, }} onRegionChangeComplete={(region) => setRegion(region)} /> <Button onPress={() => goToTokyo()} title="Go to Tokyo" /> <Text style={styles.text}>Current latitude{region.latitude}</Text> <Text style={styles.text}>Current longitude{region.longitude}</Text> </View> ); } const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, flex: 1, justifyContent: "flex-end", alignItems: "center", }, map: { ...StyleSheet.absoluteFillObject, }, text: { fontSize: 20, backgroundColor: "lightblue", }, });
Использование <polyline />
Вы можете использовать компонент из библиотеки для создания линий между несколькими координатами. Он принимает массив координат в своей опоре. Вы также можете указать дополнительные реквизиты для стилизации, такие как , и т. д.<Polyline />react-native-mapscoordinatesstrokeWidthstrokeColor
Давайте создадим путь между Токио и Тибой.
import { Polyline } from "react-native-maps"; const tokyoRegion = { latitude: 35.6762, longitude: 139.6503, latitudeDelta: 0.01, longitudeDelta: 0.01, }; const chibaRegion = { latitude: 35.6074, longitude: 140.1065, latitudeDelta: 0.01, longitudeDelta: 0.01, }; return ( <View style={styles.container}> <MapView style={styles.map} initialRegion={tokyoRegion}> <Polyline coordinates={[tokyoRegion, chibaRegion]} //specify our coordinates strokeColor={"#000"} strokeWidth={3} lineDashPattern={[1]} /> </MapView> </View> );
Сохраните координаты местоположений в соответствующих переменных и передайте их в виде массива в coordinates
свойство компонента.<Polyline />
Если посмотреть на результаты, то линия проведена прямо между этими координатами и не учитывает фактические географические пути и дороги. Для этого вам потребуется установить несколько координат между исходным и конечным местоположениями с помощью Google Maps Direction API, который возвращает все возможные маршруты между двумя местами.
Использование Google Maps Direction API
Чтобы использовать Direction API , вы должны сначала включить его для своего проекта . Обратите внимание, что для использования Google Cloud у вас должен быть действительный платежный адрес, иначе функция «Маршруты» не будет работать.
Сначала создайте вспомогательную функцию с именем getDirections
. Здесь напишите следующий код:
import {decode} from "@mapbox/polyline"; //please install this package before running! const getDirections = async (startLoc, destinationLoc) => { try { const KEY = "YOUR GOOGLE API KEY"; //put your API key here. //otherwise, you'll have an 'unauthorized' error. let resp = await fetch( `https://maps.googleapis.com/maps/api/directions/json?origin=${startLoc}&destination=${destinationLoc}&key=${KEY}` ); let respJson = await resp.json(); let points = decode(respJson.routes[0].overview_polyline.points); console.log(points); let coords = points.map((point, index) => { return { latitude: point[0], longitude: point[1] }; }); return coords; } catch (error) { return error; } };
Функция преобразует закодированные точки полилинии из свойства в массив, содержащий широту и долготу всех координат.decode()overview_polyline.points
В результате это позволит PolyLine
компоненту легко считывать координаты местоположения. Без него выдает ошибку.react-native-maps
import React, { useState, useEffect } from "react"; import { View, Text } from "react-native"; import MapView, { Polyline } from "react-native-maps"; import { decode } from "@mapbox/polyline"; const App = () => { const [coords, setCoords] = useState([]); useEffect(() => { //fetch the coordinates and then store its value into the coords Hook. getDirections("52.5200066,13.404954", "50.1109221,8.6821267") .then(coords => setCoords(coords)) .catch(err => console.log("Something went wrong")); }, []); return ( <> <MapView style={{ flex: 1 }} initialRegion={{ latitude: 52.5200066, longitude: 13.404954, latitudeDelta: 0.1, longitudeDelta: 0.1 }} > {/* finally, render the Polyline component with the coords data */} {coords.length > 0 && <Polyline coordinates={coords} />} </MapView> </> ); }; export default App;
Заключение
Теперь у вас должно быть общее представление о том, как реализовывать карты и создавать пользовательские функции поверх библиотеки. Вы можете использовать эти уроки в своей работе для создания множества типов приложений, от служб такси до поиска ресторанов, приложений для доставки и многого другого. Библиотека упрощает интеграцию карт и является важным игроком в экосистеме React Native.