Геолокация и карты
Expo Location
npx expo install expo-location
Текущая позиция
import * as Location from 'expo-location';
async function getCurrentLocation() {
const { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') return;
const location = await Location.getCurrentPositionAsync({
accuracy: Location.Accuracy.High,
});
console.log(location.coords.latitude, location.coords.longitude);
}
Отслеживание
const subscription = await Location.watchPositionAsync(
{
accuracy: Location.Accuracy.High,
timeInterval: 5000,
distanceInterval: 10,
},
(location) => {
setCoords(location.coords);
}
);
return () => subscription.remove();
Фоновое отслеживание
Для фитнес-трекеров и доставки:
await Location.startLocationUpdatesAsync('task-name', {
accuracy: Location.Accuracy.Balanced,
timeInterval: 60000,
distanceInterval: 100,
foregroundService: {
notificationTitle: 'Отслеживание активно',
notificationBody: 'Приложение записывает ваш маршрут',
},
});
Требует TaskManager.defineTask и разрешения Always.
Геокодирование
Адрес → координаты:
const results = await Location.geocodeAsync('Москва, Красная площадь');
Координаты → адрес:
const addresses = await Location.reverseGeocodeAsync({
latitude: 55.7558,
longitude: 37.6173,
});
Карты
npx expo install react-native-maps
import MapView, { Marker } from 'react-native-maps';
<MapView
style={{ flex: 1 }}
initialRegion={{
latitude: 55.7558,
longitude: 37.6173,
latitudeDelta: 0.05,
longitudeDelta: 0.05,
}}
>
<Marker
coordinate={{ latitude: 55.7558, longitude: 37.6173 }}
title="Москва"
description="Столица России"
/>
</MapView>
Кластеризация
import { Marker } from 'react-native-maps';
import ClusteredMapView from 'react-native-map-clustering';
<ClusteredMapView
style={{ flex: 1 }}
initialRegion={region}
clusterColor="#c1442e"
>
{points.map((p) => (
<Marker key={p.id} coordinate={p.coords} />
))}
</ClusteredMapView>
Пользовательская позиция
<MapView
showsUserLocation
followsUserLocation
showsMyLocationButton
/>
Стили карты
const mapStyle = [
{ elementType: 'geometry', stylers: [{ color: '#242f3e' }] },
{ elementType: 'labels.text.fill', stylers: [{ color: '#746855' }] },
];
<MapView customMapStyle={mapStyle} />
Обратные вызовы
<MapView
onRegionChangeComplete={(region) => console.log('регион изменился', region)}
onPress={(e) => console.log('клик', e.nativeEvent.coordinate)}
onMarkerPress={(e) => console.log('маркер', e.nativeEvent.id)}
/>
Разрешения
{
"expo": {
"ios": {
"infoPlist": {
"NSLocationWhenInUseUsageDescription": "Показываем ближайшие точки на карте"
}
},
"android": {
"permissions": ["ACCESS_FINE_LOCATION", "ACCESS_COARSE_LOCATION"]
}
}
}
Оптимизация батареи
- Используй
Accuracy.BalancedвместоHigh, если точность не критична distanceIntervalчтобы не получать обновления на каждом метре- Отключай отслеживание в фоне, когда не нужно
Итоги
expo-locationдля геолокацииwatchPositionAsyncдля отслеживания- Фон — через TaskManager
- Геокодирование для адресов
react-native-mapsдля карт- Кластеризация для множества точек