Предыстория
Начну с небольшой предыстории. Во время новогодних праздников мне нечем было особо заняться и я решил написать мобильное приложение, что-то вроде Zenly (социальная сеть, в которой в real-time можно увидеть, где сейчас находятся твои друзья), которое сейчас закрывает Snapchat. Решил делать это мобильное приложение на фреймворке js - React Native - для меня это казалось идеальным решением, так как такие языки как Kotlin или Swift я не особо уважаю, в силу того, что с ними ни разу не взаимодействовал. Первая задача с которой я столкнулся - это отображение карты в приложении и как на ней оставлять маркеры (в моём случае маркеры - это друзья в социальной сети). Эта тема на самом деле очень глубокая и копать в ней можно вплоть до написания своего картографического движка, но я решил воспользоваться чем-то из уже готовых решений. Из готовых решений с первым с чем я столкнулся - это интеграция Google Maps в приложение с помощью react-native-maps, однако, в современных реалиях Google не хочет предоставлять в Россию свои средства для разработчиков. Следующий вариант, который я рассматривал, это интеграция Mapbox в React Native. У Mapbox Maps SDK инструментарий мне понравился, там можно и стиль карты кастомизировать очень удобно, и весь нужный мне функционал присутствует. Однако, я всё же решил пойти дальше и наткнулся на Яндекс Карты для React Native. Они мне показались гораздо удобнее и легче в использовании в конкретно моём случае и я остановился на Яндекс Картах. В этой статье расскажу про начало работы с Яндекс Картами для React Native и базовые примеры того, что можно сделать с этой библиотекой.
Установка и инициализация Яндекс Карт для React Native
Установить библиотеку в проект можно с помощью менеджеров пакетов:
npm i react-native-yamap --save
yarn add react-native-yamap
Также, если у вас версия React Native ниже 0.60 необходима линковка библиотеки:
react-native link react-native-yamap
Далее переходим к инициализации библиотеки в наш проект. Для этого необходимо библиотеку импортировать и записать функцию инициализации, и передать в функцию строку с API-ключом, который можно получить на сайте кабинета Яндекс Разработчика.
import { YaMap, Marker } from 'react-native-yamap';
YaMap.init('ВАШ_API_КЛЮЧ');
И если вы пишете приложение для iOS, документация подсказывает, что необходимо инициализировать библиотеку в didFinishLaunchingWithOptions - функцию, которая находится в AppDelegate.m/AppDelegate.mm
#import <YandexMapsMobile/YMKMapKitFactory.h>
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
[YMKMapKit setLocale:@"ru_RU"];
[YMKMapKit setApiKey:@"API_KEY"];
return YES;
}
Добавляем карту в приложение
Библиотеку мы инициализировали, теперь можно добавлять карту в приложение. Для этого воспользуемся компонентом карты. При добавлении карты наш компонент будет выглядеть как-то так:
export default function Habr() {
return (
<>
<YaMap/>
</>
);
}
И что мы увидим, когда добавим компонент карты? Да вобщем-то ничего, он добавился, но для корректного отображения ему следует задать размеры. Для примера я сделал это как-то так. Наш компонент:
import MapStyles from './HabrStyles';
...
export default function Habr() {
return (
<>
<YaMap
style={MapStyles.map}
>
</YaMap>
</>
);
}
Стили выглядят так:
import {StyleSheet} from 'react-native';
import { vw, vh } from 'react-native-expo-viewport-units';
export default MapStyles = StyleSheet.create({
map: {
width: vw(100),
height: vh(100),
},
})
Я для указания размеров использую viewport по старой привычке с css, однако, размеры там можно задавать как угодно.
Теперь у нас карта отобразилась и теперь наше приложение выглядит вот так:
Для компонента YaMap доступно использование пропсов, которые позволят настроить карту, как нам необходимо. Например, давайте сделаем, карту, на которой будет выключен показ текущей позиции пользователя, карта будет отображаться векторным изображением в ночном режиме и также я хочу отключить поворот камеры на карте. Также хочу, чтобы при открытии карты, камера находилась на координатах 30 по широте, 30 по долготе, уровень зума был выставлен на 7, а поворот по азимуту был выставлен на 0 градусов. Это будет выглядеть так:
export default function Habr() {
return (
<>
<YaMap
showUserPosition={false}
rotateGesturesEnabled={false}
nightMode={true}
mapType={'vector'}
initialRegion={{
lat: 30,
lon: 30,
zoom: 7,
azimuth: 0,
}}
style={MapStyles.map}>
</YaMap>
</>
);
}
Тогда при открытии карты мы видим следующее:
Добавляем примитивы на карту
Следующая задача с которой я столкнулся при разработке своего приложения, это отображение информации, в моём случае, пользователя, на карте. Нам доступно несколько примитивов с помощью которых мы может отображать ту или иную информацию на карте.
Конкретно для своей задачи я воспользовался компонентом Marker, который поместил в компонент YaMap. Давайте для примера на координатах 30 по широте и 30 по долготе установим маркер на нашей карте. Это будет выглядеть так:
export default function Habr() {
return (
<>
<YaMap
showUserPosition={false}
rotateGesturesEnabled={false}
nightMode={true}
mapType={'vector'}
initialRegion={{
lat: 30,
lon: 30,
zoom: 7,
azimuth: 0,
}}
style={MapStyles.map}
>
<Marker
point={{ lat: 30, lon: 30 }}
/>
</YaMap>
</>
);
}
И тогда на экране мы увидим следующее:
Мы добавили совсем маленький, практически незаметный маркер, с помощью пропса увеличим его:
export default function Habr() {
return (
<>
<YaMap
showUserPosition={false}
rotateGesturesEnabled={false}
nightMode={true}
mapType={'vector'}
initialRegion={{
lat: 30,
lon: 30,
zoom: 7,
azimuth: 0,
}}
style={MapStyles.map}
>
<Marker
point={{ lat: 30, lon: 30 }}
scale={5}
/>
</YaMap>
</>
);
}
Вот так уже лучше. Но я хочу маркер как-то кастомизировать. Для этого можно с помощью пропса souce передать изображение в маркер, но мне интереснее другое, с помощью пропса children можно передать в маркер компонент, который собственно говоря у нас и будет отображаться на заданных координатах. Именно компонентом я хочу передавать изображение в маркер, потому что в случае если мы передаём ссылку на изображение без компонента, то если изображение имеет разрешение 100x100 пикселей, оно так и отображаться будет. Масштабировать можно при помощью scale, однако, тогда если мы отрисовываем много маркеров, у каждого из которого своё изображение и их надо как-то унифицировать, придётся задавать-подбирать scale для каждого отдельного маркера. Также я хочу добавить изображению обводку и сгладить углы.
export default function Habr() {
return (
<>
<YaMap
showUserPosition={false}
rotateGesturesEnabled={false}
nightMode={true}
mapType={'vector'}
initialRegion={{
lat: 30,
lon: 30,
zoom: 7,
azimuth: 0,
}}
style={MapStyles.map}
>
<Marker
children={<Image
style={MapStyles.marker}
source={{uri: 'ВАШЕ_ИЗОБРАЖЕНИЕ'}} />}
point={{ lat: 30, lon: 30 }}
/>
</YaMap>
</>
);
}
Рассмотрим следующий примитив - Circle. Тут, я думаю, всё понятно из названия. Принимает он координаты центра окружности и её радиус. Также можно передавать другие параметры. Давайте допустим сделаем синий круг с тёмно-синей обводкой. Стоит также обратить внимание, что все примитивы принимают пропсом параметр zIndex, от которого будет завить, как они будут друг на друга накладываться.
export default function Habr() {
return (
<>
<YaMap
showUserPosition={false}
rotateGesturesEnabled={false}
nightMode={true}
mapType={'vector'}
initialRegion={{
lat: 30,
lon: 30,
zoom: 7,
azimuth: 0,
}}
style={MapStyles.map}
>
<Marker
children={<Image
style={MapStyles.marker}
source={{uri: 'ВАШЕ_ИЗОБРАЖЕНИЕ'}} />}
point={{ lat: 30, lon: 30 }}
zIndex={4}
/>
<Circle
center={{lat: 30, lon: 30}}
radius={60000}
fillColor='#5789d9'
strokeColor='#154ca3'
strokeWidth={4}
zIndex={5} />
</YaMap>
</>
);
}
Также существуют примитивы Polygon и Polyline, которые позволяют по точкам строить фигуры и линии соответственно. Стиль для этих примитивов задаётся также, как и для круга. Для примера давайте закрасим фигурой город Каир на карте, а также обозначим реку Нил линией.
export default function Habr() {
return (
<>
<YaMap
showUserPosition={false}
rotateGesturesEnabled={false}
nightMode={true}
mapType={'vector'}
initialRegion={{
lat: 30,
lon: 30,
zoom: 7,
azimuth: 0,
}}
style={MapStyles.map}
>
<Marker
children={<Image
style={MapStyles.marker}
source={{uri: 'ВАШЕ_ИЗОБРАЖЕНИЕ'}} />}
point={{ lat: 30, lon: 30 }}
zIndex={4}
/>
<Circle
center={{lat: 30, lon: 30}}
radius={60000}
fillColor='#5789d9'
strokeColor='#154ca3'
strokeWidth={4}
zIndex={5} />
<Polygon
points={[
{ lat: 30.540273, lon: 31.182331 },
{ lat: 30.070791, lon: 31.928108 },
{ lat: 29.233658, lon: 31.228942 },
{ lat: 29.983355, lon: 30.622998 },
]}
fillColor='#5789d9'
strokeColor='#154ca3'
strokeWidth={4}
zIndex={5}
/>
<Polyline
points={[
{ lat: 29.988660, lon: 31.207694 },
{ lat: 29.364817, lon: 31.176281 },
{ lat: 28.634771, lon: 30.862143 },
{ lat: 27.490336, lon: 30.839704},
]}
fillColor='#5789d9'
strokeColor='#154ca3'
strokeWidth={4}
zIndex={4}
/>
</YaMap>
</>
);
}
Думаю, общая концепция работы с примитивами на Яндекс Картах понятна. Также стоит отметить, что все они принимают в пропс onPress функцию, которая будет выполняться по нажатию на них и все эти примитивы необходимо импортировать перед использованием:
import { YaMap, Marker, Circle, Polygon, Polyline } from 'react-native-yamap';
Итог
В конце хочу сказать, что выше приведенные примеры, это совсем базовая работая с Yandex Maps SDK. Библиотека позволяет простраивать маршруты, использовать геокодер, в ней также можно настраивать стили для карты. Мне на эту тему есть что ещё сказать, как про Yandex Maps SDK, так и про Mapbox Maps SDK. Интересно было бы почитать комментарии, услышать, интересно это кому-то или нет, стоит дальше рассказывать про этот инструментарий или что-нибудь другое.
Комментарии (3)
UserHome
27.01.2023 22:11+1Никита, раскажите про ВАШ_API_КЛЮЧ, а также расценки на пользование картографическим фреймворком: столько то запросов в год - столькото рублей в год, еще чуть поболее - еще чутка подбавить и сравни с аналогом Google Maps и другими. Интересно какая фирма окажется более экономически выгодной в плане разработки, тестирования и работы вашего приложения с сервисом картографии. Вам же не бесплатно предоставили право использования чужой инфраструктуры и технологических наработок в вашем приложении?
Avadon
28.01.2023 18:24Также можно поставить либу MapBox и использовать тайлы СтарЛайн Карт. Там есть все: векторные тайлы, дизайнер карт, геокодер, роутинг и куча полезных API.
vkompaniec
Хорошая библиотека, но она какое-то время не обновлялась. Сейчас последнее обновление от сентября прошлого года. Уже появились новые ишьюс и еще много старых. Из интересных глюков - первый показ карты. Сетка есть, кнопки яндекса и лейбл есть, карты нет. Если приложение свернуть/развернуть, появляется.