- Introduction
- Setting Up Project
- Understanding the MapView Props
- Creating the Animation
- Conclusion
- </> Full Code
Introduction
Hey there, fellow developers! Ever thought about giving your React Native maps a fresh twist? Today, we're diving into creating a bird's-eye view animation, offering users an engaging and elevated perspective. And the best part? It's completely free to use the map and the animation! Just a few lines of code and we got ourselves a nice bird's eye view animation! Our goal is to create something like the following -
Setting Up Project
- Create an Expo Project
Add the MapView dependency
npx expo install react-native-maps
Create a basic Map View
import React from "react";
import { StyleSheet, View } from "react-native";
import MapView from "react-native-maps";
export default function App() {
return (
<View style={styles.container}>
<MapView style={styles.map} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
map: {
width: "100%",
height: "100%",
},
});
and you should have something like the following.
Great we are already halfway there!
Understanding the MapView Props
Now for the fun part - understanding the relevant MapView props! When reading the full MapView documentation you can see the MANY props but we will only need the following:
mapType: Prop controlling which map layer type we are using. I use "satellite" since we only care about the map and not the pins nor pin labels, but feel free to use any other layer.
camera: Prop controlling which region we are viewing on screen, the heading (direction faced), the zoom level, and the 'pitch' (up-down angle).
Let's now test out these props! Let's try mapping the pyramids from a strictly top view.
<MapView
style={styles.map}
mapType="satellite"
camera={{
center: {
latitude: 29.978,
longitude: 31.131,
},
pitch: 0, // Change this value to set the desired pitch
heading: 0, // Direction faced by the camera, in degrees clockwise from North.
zoom: 15.5, // Closer values mean a higher zoom level.
}}
/>
and we get the following -
Relative to the original, modifying the pitch to 90 we get -
We can see we have created an angle of depression.
Next - relative to the original, modifying the heading to 180 we get -
We can see we have ended up on the other side of the imaginary orbit focused on the pyramids.
We now know that pitch controls the angle of depression focused about the specified region and the heading controls the direction we are facing on an imaginary orbit about the specified region. Now lets animate it!
Creating the Animation
In order to create the animation, we must first understand how the animation is going to work. We want the camera to stay focused on a region as it orbits the specified region.
The only thing we will need to update is where we are on that circle, thus we only need to update the heading every so often. The center and the pitch will remain the same for the animations entirety.
To update the heading every so often we will need to update the headings state, thus we will use useState. We will also be updating the state on an interval so that we can get a "bird's eye view" orbiting animation. Below is what we add before the return -
//animation to circle map
const [heading, setHeading] = useState(0);
useEffect(() => {
const intervalId = setInterval(() => {
setHeading((prevHeading) => (prevHeading + 0.1) % 360); // Increment heading, and reset to 0 after reaching 360
}, 10);
return () => clearInterval(intervalId); // Clear the interval when component is unmounted
}, []);
and update the header variable to be dynamic -
heading: heading, // Direction faced by the camera in degrees clockwise from North.
We are done and should have something like this now -
Conclusion
And that's a wrap! With the bird's-eye view effect in place, your React Native maps just got a whole lot cooler. It's these thoughtful touches that can make an app truly stand out. Keep exploring, keep innovating, and as always, happy coding!
Please like and follow me on Github @noahvelasco!
</> Full Code
import React, { useState, useEffect } from "react";
import { StyleSheet, View } from "react-native";
import MapView from "react-native-maps";
export default function App() {
//animation to circle map
const [heading, setHeading] = useState(0);
useEffect(() => {
const intervalId = setInterval(() => {
setHeading((prevHeading) => (prevHeading + 0.1) % 360); // Increment heading, and reset to 0 after reaching 360
}, 10);
return () => clearInterval(intervalId); // Clear the interval when component is unmounted
}, []);
return (
<View style={styles.container}>
<MapView
style={styles.map}
mapType="satellite"
camera={{
center: {
latitude: 29.978,
longitude: 31.131,
},
pitch: 90, // Change this value to set the desired pitch
heading: heading, // Direction faced by the camera, in degrees clockwise from North.
zoom: 15.5, // Closer values mean a higher zoom level.
}}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
map: {
width: "100%",
height: "100%",
},
});
Top comments (0)