I’m using Expo and React Native Maps and I’m trying to figure out how to have 2 points, an origin and a destination, then orientate the map so that the destination is at the top and the origin is at the bottom. I figured out how to calculate the heading and set that using setCamera. But now I want the map to fit to the map to the origin and destination points, but the problem is when I call fitToCoordinates, the map resets to a heading of 0. Does anyone know how to do something like fitToCoordinates with a heading?
Here's the code:
import React, { useRef } from 'react';
import { Dimensions, StyleSheet, View } from 'react-native';
import { StatusBar } from 'expo-status-bar';
import MapView from 'react-native-maps';
// Converts from degrees to radians.
function toRadians(degrees) {
return (degrees * Math.PI) / 180;
}
// Converts from radians to degrees.
function toDegrees(radians) {
return (radians * 180) / Math.PI;
}
function getHeading(origin, destination) {
const originLat = toRadians(origin.latitude);
const originLng = toRadians(origin.longitude);
const destLat = toRadians(destination.latitude);
const destLng = toRadians(destination.longitude);
const y = Math.sin(destLng - originLng) * Math.cos(destLat);
const x =
Math.cos(originLat) * Math.sin(destLat) -
Math.sin(originLat) * Math.cos(destLat) * Math.cos(destLng - originLng);
const heading = toDegrees(Math.atan2(y, x));
return (heading + 360) % 360;
}
const origin = { latitude: 47.58991363446258, longitude: -122.24398815305646 };
const destination = {
latitude: 47.596003585463656,
longitude: -122.32888303102513,
};
const center = {
latitude: (origin.latitude + destination.latitude) / 2,
longitude: (origin.longitude + destination.longitude) / 2,
};
const latitudeDelta =
Math.abs(origin.latitude - destination.latitude) + 0.00025;
const longitudeDelta =
Math.abs(origin.longitude - destination.longitude) + 0.00025;
const heading = getHeading(origin, destination);
export default function App() {
const mapRef = useRef(null);
console.log('origin', origin);
console.log('destination', destination);
console.log('center', center);
console.log('latitudeDelta', latitudeDelta);
console.log('longitudeDelta', longitudeDelta);
console.log('heading', heading);
return (
<View style={styles.container}>
<MapView
style={styles.mapStyle}
ref={mapRef}
initialRegion={{
latitude: center.latitude,
longitude: center.longitude,
latitudeDelta,
longitudeDelta,
}}
onMapReady={() => {
console.log('mapReady...');
// This orientates the map with the origin on bottom and destination on top
// You can see that when the map first loads,
// but the map isn't fit to the points
mapRef.current.setCamera({ center, heading });
// 5 seconds after the map loads,
// this runs and does fit the map to the points,
// but it sets the heading back to 0
setTimeout(() => {
console.log('fitting to coordinates');
mapRef.current.fitToCoordinates([origin, destination], {
animated: false,
});
}, 5000);
}}
scrollEnabled={true}
/>
<StatusBar style='auto' />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
mapStyle: {
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
},
});