Яндекс Карты и React Native

от автора

Предыстория

Начну с небольшой предыстории. Во время новогодних праздников мне нечем было особо заняться и я решил написать мобильное приложение, что-то вроде 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 можно передать в маркер компонент, который собственно говоря у нас и будет отображаться на заданных координатах. Именно компонентом я хочу передавать изображение в маркер, потому что в случае если мы передаём ссылку на изображение без компонента, то если изображение имеет разрешение 100×100 пикселей, оно так и отображаться будет. Масштабировать можно при помощью 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. Интересно было бы почитать комментарии, услышать, интересно это кому-то или нет, стоит дальше рассказывать про этот инструментарий или что-нибудь другое.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Стоит писать дальше про работу с картами на React Native?
0% Да, интересны другие варианты (Mapbox, Google Maps) 0
0% Да, интересно про Yandex Maps 0
0% Нету смысла 0
Никто еще не голосовал. Воздержавшихся нет.

ссылка на оригинал статьи https://habr.com/ru/post/713322/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *