How to Fly to a Location With the Mapbox Maps SDK for React Native

React Native

JavaScript LogoUsing the flyTo() method, you can zoom out, move to a target location, and then zoom back in. To do this, you only need to tell the MapBox api the coordinates of the target location and the animation duration.

Being able to move from one geo-specific location to another is a critical feature for any map application. At first, users may be happy just to know where they are. At some point, though, you’ll want to offer them the opportunity to go to another location. And you’ll be able to do this, since the react-native-mapbox-gl API has a flyTo() method which provides powerful animation for just this purpose!

At first glance, the moveTo() method may seem like a logical choice, but if you try to implement it, you’ll soon notice that it maintains the current zoom level, which is a major drawback. In some contexts, it may suffice, but for the most part, it is not the best solution for moving from one place to another when the distance is more than a few miles, and the zoom level is an issue. Take a look:

package.json

Above we have the contents of package.json, with dependencies on react, react-native and @mapbox/react-native-mapbox-gl. Now take a look at the examples below.

flyTo() method – Example # 1

We have the basic syntax for the flyTo() method in Example # 1, which belongs to the instance of the map. In our case, we have an instance property named “_map“. We’ll see how this instance property is declared in Example # 3. The flyTo() method takes two arguments: the target coordinates and animation duration. The target coordinates is an array and it should contain the longitude and latitude of an earth location to which you want to “fly” (and they must be in that order). The animation duration tells MapBox how long this “fly to” action should take, because the reality of calling the flyTo() method is that it animates the map. Now fortunately, MapBox takes care of the implementation details for this animation, and all we need to do is let MapBox know what the duration of this animation should be. The value you provide should be in milliseconds (i.e. a value of 1000 would equal one second).

Context for this._map.flyTo() – Example # 2

Putting a little context around the call to this._map.flyTo() in Example # 2, we’ve added a TouchableOpacity component to the application, which, in a nutshell, enables us to make something “touchable.” That is, it can react to a touch and we can add a handler for that touch event. We’ve assigned an anonymous function to the onPress method of the TouchableOpacity, and inside of that anonymous function, we call this._map.flyTo(), passing it the coordinates of the location on earth to which we’d like to “fly”. As a second argument, we provide the number 2500, which means that we want the “fyTo” animation to have a duration of 2.5 seconds. The coordinates that we have provided to this._map.flyTo() are for Columbus Circle in New York City, and the TouchableOpacity has a text component as a child, with the text: “NYC”. So, by pressing this button, the user “flies to” Columbus Circle in New York City.

Full Working App – Example # 3

The full code for our basic working app is in Example # 3. Everything we covered in Example # 2 is in play here, so I won’t take up time repeating that, but one thing to note is line # 13, where we take advantage of the MapboxGL.MapView ref” property. By assigning an anonymous function, we take the argument that is passed to that function (“c”), and assign it to the property: “this._map”. This provides a reference to the map instance. Let’s face it, we’d basically be stuck in the water without the MapboxGL.MapViewref” property, so I’m amazed that it’s not mentioned in the documentation (hint hint MapBox folks!).

TouchableOpacity – Example # 4

I’ve added three more instances of the TouchableOpacity component in Example # 4, giving us four “buttons”: we can fly to New York City, Boston, Paris or Rome. I’ve followed the exact same patterns in the code from Example # 3, so again, I won’t take up time going over all that. The main thing I do want to point out, though, is: instead of assigning an anonymous function to the onPress property of each TouchableOpacity, I’ve created methods for each (i.e. “flyToNyc”, “flyToBoston”, “flyToParis” and “flyToRome”). This makes for much cleaner code, especially for our render() method (lines 31 to 66). In each case, I’ve used this pattern: this.METHOD_NAME.bind(this). This allows us to bind each method to the class instance (i.e. this._map) so that we have access to the class’s this._map property.

styles.js

Above, I’ve included the styles for the working code, just in case you wanted to quickly do a copy-and-paste, and get this application up and running in your local environment.

Summary

So, it’s obvious that the folks at MapBox really had their thinking-caps on when they developed the .flyTo() method. It is essentially an animation method, but what is so impressive is the minimal level of effort required to leverage it. Overall, the animation is smooth and it really does provide a “fly to” feeling in that it first zooms out, then moves to the target destination, then zooms in. And you’re in control, since all of this is done in the amount of time you specify in the animation duration argument. And the performance is impressive.

How to create a React Native side-menu with react-native-drawer

React Native

JavaScript LogoThe react-native-drawer module makes it easy to implement a side-menu in your React Native application.

In the article: “Getting Started with the Mapbox Maps SDK for React Native” I walked you through the basic steps needed to render a Mapbox Map in a React Native application. So, I thought this might be a good time to mention the side-menu, which is a fairly typical component in any mobile application, as it provides a container for critical tasks such as navigation or setting options. In this article, I will explain how to create a side-menu, using the react-native-drawer npm module. I’ll explain the basic syntax and make a few suggestions on how to format your code, and… spoiler alert: the react-native-drawer module is easy to implement and the syntax is very straightforward.

If you are just getting started with React Native, or building a new mobile application from scratch, the react-native CLI is incredibly helpful. By simply executing react-native init APPLICATION_NAME in your terminal, you’ll have a fully functional application in less than a few minutes. But what’s so magical is that for the entire few minutes, the react-native CLI is busy building that application for you. In fact, it even executes a first-time npm install for you. Pretty bad-ass.

But, I will mention that the application that the react-native CLI builds out for you consists of a simple view with some text. Of course we can’t complain; the react-native CLI has done a great deal of work, sparing us the tedious details of staring at a blank text file, wondering where to begin. So, one of the first steps in snazzing-up this “hello world” is to add a side menu, which will pretty much be a “hello world” side-menu, but you can copy-paste this code into your app and be up and running in minutes.

package.json

Above, we have our package.json file. Nothing too special going on here; we just need react, react-native and react-native-drawer. In the devDependencies section, babel-jest, babel-preset-react-native, jest and react-test-renderer were configured for us by the react-native CLI. You should be able to copy and paste this into your application, then fire up your emulator.

Example # 1

In Example # 1 you see the very basics of how the side-menu component is arranged in your code. In fact, it’s so basic that it won’t actually work yet. So what I’ll do is demonstrate how you wrap your application code in the Drawer component. Drawer is an object that we create by requiring the react-native-drawer module. (You’ll see the details for this in Example # 5.) Meanwhile, the main thing to keep in mind is that the Drawer component wraps your application code in your class’s render() method, and your application code would go where you see: “APPLICATION_CONTENT_GOES_HERE”.

Example # 2

Example # 2 is similar to Example # 1. The main difference here is the addition of two properties to the Drawer component. The content property is where you set the content for the Drawer component, which is where you see “CONTENT GOES HERE“. Now in theory, you could put a string there. I feel pretty sure, however, that you’ll never want to do that.

I suggest providing a reference to a method that will render your content. If you think about it, this is ALL of the content for your side-menu. I don’t think there is any chance that the side-menu content will be just a few words or something. So it makes sense to provide a method reference, and in that method you render your content. This way, you can break that method out accordingly into smaller sub-methods. You can then include any logic that is needed to properly render your content.

The styles property is where the styling for the side-menu component goes (i.e. where you see: “YOUR_CUSTOM_STYLES“). Now while you can provide an inline object literal here, again, I recommend you provide a reference to an object that contains your styles for cleaner and more manageable code.

Example # 3

In Example # 3, I added an event handler for the onClose() property. This is not a requirement, but I added this piece of code because you may want to know when the user closed the side-menu. For example, on menu closed, you may want to emphasize or deemphasize another element. Here too, you do not have to handle this event, but it’s just good to know that you can if needed.

Example # 4

In Example # 4, I’ve added more properties that give the side-menu a bit more of a finished feel. Take a look at line # 4: type=”overlay” tells react-native that we want this side menu to have an overlay look and feel. And setting tapToClose to true allows the user to close the menu simply by tapping anywhere outside of the menu. I’d recommend leveraging this feature, since you probably don’t want to require the user to click a dedicated button in order to close the menu. But that, of course, is your choice.

So, in an effort to keep things brief, I’ll skip the in-depth discussion of openDrawerOffset, panCloseMask, closedDrawerOffset, panOpenMask, captureGestures and acceptPan. They all have to do with visual aspects of the side-menu and are worth looking into when you have time.

Example # 5

There is a lot going on in Example # 5 as it is all the code for the working application. Take a look at the renderSideMenuContent() method on line # 13 and the renderMainContent() method on line # 23. In these methods, I’m rendering the content for both the side-menu and the rest of the application, because I wanted to keep the render() method on line # 39 as clean as possible. This way, you can get a sense of how the application is structured just by looking at the code between line # 39 and line # 66. And then, the implementation details for child components such as the side-menu content and the application content are broken out into their own methods.

How to Show Points on a Mapbox Map With React Native

React Native

JavaScript LogoThe key to rendering MapBox markers in your React Native application is implementing the MapboxGL.PointAnnotation component.

In the article: “Getting Started with the Mapbox Maps SDK for React Native,” I covered the absolute basics needed to get a MapBox map to render in your React Native application. The level of effort was low, and the scope of the article was minimal, but that was the whole idea. We wanted to stick to the basics and we did, by rendering a map and setting the center coordinates to Columbus Circle in New York City. In this article, however, our goal is to set a number of markers on a map.

So, markers, what are they? Well, they’re the common features of map applications that allow us to provide a visual cue that refers to a location on earth. And depending on your business requirement, your markers can often extend the richness of your application. For example, you can attach click or press event handlers and provide geo-specific information to the user. Or, you could customize the image that is used for the marker to further enhance the user experience. Now the key to rendering markers with MapBox is implementing the MapboxGL.PointAnnotation. According to the mapbox GitHub page, this component represents “…a one-dimensional shape located at a single geographical coordinate.”  While that definition may be a bit dry, it just means that it is the component that will become the marker on your map.

package.json

Above we have the contents of package.json. We have dependencies on react, react-native and @mapbox/react-native-mapbox-gl. Let’s take a look at an example:

Example # 1

Now there is a lot going on in Example # 1, but let’s break it down. As I mentioned in the previous article, we need to use the MapboxGL.setAccessToken method to let MapBox know what our access token is. So, just skip down to line # 64: the render() method. Here, we render the MapBox map via the MapboxGL.MapView component, which takes care of all the heavy lifting when it comes to rendering the map. The sole child element of MapboxGL.MapView is the return value of our renderAnnotations() method. So let’s go ahead and take a look at that method.

Look at the renderAnnotations method on line # 54. Here, we create a for-loop, which iterates over the state.coordinates array. And for each iteration, we call the renderAnnotation() method, passing the value of the “i” variable, which is just a counter. In this method, we are simply pushing elements into the items array, which is a private variable, and we return that array. So, now, back at line #74, it is this array of MapboxGL.PointAnnotation components. Let’s just go ahead and take a look at the renderAnnotation() method.

Take a close look at the renderAnnotation() method on line # 30. You’ll see that it takes counter as an argument, which we’ll need in order to understand the coordinates of the marker we create. This method returns a MapboxGL.PointAnnotation, which is constructed in this method. The constants id, coordinate and title are used to help make this MapboxGL.PointAnnotation unique. The sole child element is a react-native Image component instance. This image you use is arbitrary, so go ahead and use any image you want. We make reference to “../common/images/marker.png”, which is a relative path in our application. The most important part of this method is the coordinate constant. We use the counter variable to get a reference to one of the state.coordinates array elements, and it’s here that we are able to give this MapboxGL.PointAnnotation component a geographic presence on our map. Nice.

Summary

Overall, in this example we did three things. First, we rendered a MapboxGL.MapView. Second, we executed a method whose return value became the sole child element of the MapboxGL.MapView component. That method looped through all of the coordinates that we stored in state.coordinates. And third, we used a for-loop to iterate the state.coordinates array and render a MapboxGL.PointAnnotation for each coordinate in that array. So, on the whole, this approach requires relatively little code. If you’re new to React Native, however, it might take a little getting used to. But I think that you’ll find that outside of the React Native learning curve, rendering markers on the map is fairly simple, and once you do master it, you’ll find it to be a great addition to your tool belt.

Getting Started with the Mapbox Maps SDK for React Native

React Native

JavaScript LogoMapbox’s react-native-mapbox-gl module simplifies the process of generating a map in your React Native application.

At first, I was a bit hesitant to embrace Mapbox because I have always been so impressed with Google Maps. Until recently, I’d had virtually no motivation to look elsewhere. After all, Google had made rendering and manipulating maps so effortless. But, now that I’ve spent some time with it, I must admit that Mapbox is a formidable competitor to Google Maps. Now, I would like to see a more robust API, especially when it comes to map event handlers. But, the more time I spend with Mapbox, the more knocked-out I am with it. So, something for you to think about: if you’re building a React Native application that leverages maps, the react-native-mapbox-gl module is quite a life saver.

For one thing, when it takes less than a few minutes to get a module working in an app, I pay attention. And that was exactly what happened with react-native-mapbox-gl. After an initial npm install –save, I was up-and-running. I will note, however, that the documentation is a bit of a disappointment, as it is minimal, fairly dry and lacking in working example code. That said, though, it was at least up to date and, for the most part, the various properties and methods worked as advertised. In fact, once you get the map to render in your React Native application for the first time, it kind of feels like magic. The map renders so smoothly and it’s almost embarrassing how little code you need to write, in order to spin-up a pretty slick-looking map-based application.

package.json

Above, we have our package.json file. Nothing too special going on here; we just need react, react-native and @mapbox/react-native-mapbox-gl. You should be able to copy and paste this into your application, then fire up your emulator.

Example # 1 – MapboxGL.MapView

In Example # 1 we start out by importing our dependencies. After that, we need to set the access token for the application. That’s done by calling the setAccessToken method of the MapboxGL module. Then, in our class, we render a MapboxGL.MapView, nested inside of a React Native View. There is a slight problem, though; we don’t see too much after the map is rendered. So let’s fix this by setting the zoomLevel property.

Example # 2 – Setting the zoomLevel property

In Example # 2, we add zoomLevel as a property of the MapboxGL.MapView, and set it to “1”. Now we see a map in our emulator. Unfortunately, though, we are in the middle of the Atlantic Ocean, which is probably not where we want to be. Okay, so let’s take care of that by setting the centerCoordinate property.

Example # 3 – Setting the centerCoordinate property

In Example # 3, we set the centerCoordinate of the MapboxGL.MapView, to the const “columbusCircleCoordinates“. This is an array that contains the latitude and longitude of Columbus Circle in New York City. So this has forced the map to render a specific location on earth, ensuring that everyone sees the same thing when they start the application.

Summary

So, MapBox clearly wants you to use to their product, as evidenced by how easy they make it to spin-up a map in your application. Their react-native-mapbox-gl module extends this facility to React Native applications. Now the key to rendering a map is the MapboxGL.MapView. So just be sure to set the centerCoordinate property to valid coordinates in an array (i.e. a set of latitude and longitude values for some place on earth).

Now, as you can well imagine, this article merely scratches the surface of what’s possible. My goal here was to simply provide a very high-level explanation of how to render a MapBox map in your React Native application. I recommend this SDK. There is a fairly robust set of properties and methods here that really makes your maps come alive.