DEV Community

loading...
Cover image for Building a geolocation app using Google Maps API in Vanilla JavaScript

Building a geolocation app using Google Maps API in Vanilla JavaScript

ritaxcorreia profile image Rita Correia Updated on ・8 min read

Recently I worked on this geolocation-based app that fetches and maps real-time availability of London’s Santander Bikes with Navigator, Google Maps API, Transport For London API. All in vanilla JavaScript.

💻 You can see mine working here💻

I thought it would be good to share a step-by-step guide on how to build it. This could be easily replicated for your own city, providing the local authorities or the service you want to use have an API. A similar take would be fetching local shops or restaurants from the Google Places API, and getting reviews or any other data.

First of all, we want to breakdown our plan into small tasks, so here’s what we need to do:



Steps

1. Get the users location from the browser

2. Render a Google map and create a request to Google Maps using the users location

3. Create a request to Travel For London (TfL) for bike information

4. Parse the Tfl API responses and add the data to the map

5. Retrieve specific info and create and InfoWindow

6. Add bikepoint info and image elements to the InfoWindow

7. Add custom markers

1. Get the user's location from the browser

In order for this app to be more relevant to a Londoner, we want to retrieve the user's location and show the bikes available nearby.
"Right, but how on earth do we do that?", you ask. 🧐

We will use the Navigator object for this. The Navigator object lives under the hood in your browser, and it allows scripts to query state and to register themselves to carry on some activities.
There's a lot of properties in the Navigator object, which you can read more about here, but for this purpose we want to use Geolocation.

The Navigator.geolocation read-only property returns a Geolocation object that gives Web content access to the location of the device. This allows a Web site or app to offer customised results based on the user's location.

Once we call navigator.geolocation, it will prompt the user to allow for their location to be shared. If you're on Google Chrome you will see this alert:

user_your_location

In Firefox, for example, you will likely have to change the geolocation sharing permissions in the settings.

This will be done on pageload so we can handle the success case (as in, getting the user's current position).

01_Get_Users_Location

We take in createMap as parameter. This will be a function that we'll create in Step 2.
If sharing location was not allowed, we will get an error on the console.

2. Render a Google map and create a request to Google Maps

For the next step, we want to render a Google map on our page which we'll wrap in a function.
You will have to sign up with Google Maps Platform and get an API key. Here's how you get started.

Once you have your API key, you'll have to include it in your Maps JavaScript API request as per the documentation. Include the Google script tag in your html file.

02_render_google_map_center_on_location

Then, we create a request to Google Maps using the user's location. The position.coords are retrieved from navigator.geolocation.getCurrentPosition() from Step 1.

map is just an id given to a <div> so we can use it as a selector. We want to center the map based in the current location, so we use center: { lat: latitude, lng: longitude } which store our position.coords. We also want to tweak the zoom property so it's more zoomed in than the default value.

Here's more on geolocation using the Google Maps API, if you would like to try a different approach.

Within the createMap function we also want to invoke the getBikeData(), which we'll create in the next step.

Destructuring objects

const { latitude, longitude } = position.coords;
Enter fullscreen mode Exit fullscreen mode

If you've never came across this weird looking syntax this is called destructuring. This was a feature added to ES6 and you can read more about it here.
Destructuring on objects lets you bind variables to different properties of an object. You specify the property being bound, followed by the variable you are binding its value to.

3. Create request to Transport for London API for bike information.

Now we'll write our getBikeData() function, where we'll create a fetch request to Transport for London API for real-time bike data.

We don't need an API key to fetch data from the TfL API, so we simply use the endpoint provided to retrieve bikepoint data. We'll receive the data in JSON.

03_tfl_getBikeData_Function

Once the fetch response is successful, we want to add our bike markers. We'll create a function for that shortly.

There's several types of data you can get from TfL, which you can access here.

4. Parse TfL API response and add bike locations to map

04_parseAPI_addlocationstomap

We want to parse our TfL API response where we take in bikepoints as our function's parameter.

We'll have quite a few bikepoints to parse so we'll run a forEach loop on each of them. We want to store the bikeLocation as a variable, which will store each bikepoint's latitude and longitude.

Then, for each of them, we want to create a Google marker, so we'll use one of the Google's functions for that. Relevant documentation on markers here. The Google marker is in fact an object which has position, map, and icon as properties. Position will take an object with the bikepoint latitude and longitude. Map will refer to the map we've previously created. And lastly, icon refers to the marker image, which will come to on our last step.

Within our addBikeMarkers function, we also invoke createBikeInfo() with bikepoint and marker as parameters. You guessed it, we'll jump onto that now.

This is how your app should look like at this point, with gorgeous markers for each Santander bike point. Gorgeous!

Screenshot 2020-11-11 at 09.09.16

5. Retrieve specific TfL info and create an information window for when a user selects a bike point

It's nice to have all the bikepoints mapped, but we need to provide more info to the user. What happens when you click on a marker? We want to display a window with all info such as number of bikes available, number of spaces available and number of docks in each bikepoint.

05_create_infoWindow

We create a function that retrieves and stores this data so we can then display it in a user-friendly format. This window will be prompted when each marker is clicked on.

You'll see in the JSON data, that the Place object has an addtionalProperties array which contains the nbBikes, nbDocks and nbSpaces. This actaully gives us real-time values, so we can display an accurate status of all bikepoints in London.

If you notice that there's a mismatch in these numbers (i.e. nbDocks - (nbBikes + nbSpaces) != 0), this indicates broken docks.
In order to find the exact property we want (nbBikes, nbDocks, nbSpaces), we use the find() array method so it can find the exact key within that object.
I'm logging a few bits here to confirm that the data that is being pulled is correct.

Finally, we add an event listener to each marker. Please note, that this is in fact using a Google method that replaces addEventListener. In here, we use addListener instead to interact with the Google marker. More on events on the Google Maps API documentation here.
We call the createInfoWindowForMarker() function (that we will create in the next step) to where we will pass in marker, bikepoint and bikeInfo as arguments.

6. Add bikepoint info and image elements to the InfoWindow

06_creates_infoWindow_for_marker

Almost there! In this function we will want to create a InfoWindow to display our bikepoint data.

InfoWindow is a type of overlay provided by Google Maps. It displays content (usually text or images) in a popup window above the map, at a given location. You can read more on InfoWindows here

First, we declare the infoWindow variable outside the function so it remains in global scope, which we'll assign with a new.google.maps.InfoWindow inside our function. This Google Maps function will take in an object literal which specifies the parameters for displaying the info window.
The one we will use is content, which is the equivalent to an innerHtml/innerText in JavaScript.
In here, we want to pass in html to the DOM, creating a div that holds an image and the data we fetched from the TfL API (the bikepoint name, number of bikes available, number of spaces available, number of docks and also the bike availability percentage). We calculate this percentage in a separate variable above.

You'll see that the first line in our code block here tells an existing open infoWindow to close. We only want to show one infoWindow at a time, so this guarantees that if there is already an infoWindow open this will be closed, so a new one can be displayed.

infoWindow.open(map, marker);
map.setCenter(marker.getPosition());
Enter fullscreen mode Exit fullscreen mode

Lastly, we want to open a new infoWindow which will display the real-time bikepoint info. We pass in the map and marker as arguments so it's linked to the marker trigged by the user click. We also want to center the infoWindow in our map. Again, we use setCenter which is a built-in method that we can use with the Google Maps map, which then takes getPosition() chained to marker. getPosition() is a Google Maps method associated to marker. If you'd like to learn more on Google Maps map and marker methods, go here.

Et voila! What a beaut.

Screenshot 2020-11-26 at 10.53.58

7. Add custom markers

Screenshot 2020-11-26 at 13.20.03

This is entirely optional as we already have a fully-functioning geolocation based app that tells us the availability of public-use bikes in London. 🤩

For our final step, we just want to give it a little personal touch and add our own custom marker images.

07_icon_base

Remember in Step 4 when we created our marker? One of the properties the marker object takes is icon. The google.maps.Icon interface is a structure that represents a Marker icon image. There's quite a few properties associated to icon, you can learn more on that here.

For our InfoWindow we will use url (pulling an image file of your choice), scaledSize (instantly scaling the original image to the desired size), and origin and anchor (which will position the marker image in correspondence to the location of the marker on the map).

There we have it, a geolocation-driven app using Navigator, Google Maps API and fetching data from the Transport for London bikes API.

Screenshot 2020-11-11 at 11.36.24

-

This is my first ever technical blogpost so would love to know if you found this helpful in any of your projects using the Google Maps API! Your constructive feedback is appreciated.

Discussion

pic
Editor guide
Collapse
waleed__barakat profile image
Waleed Barakat

Awesome, looks great app. Thanks

Collapse
ritaxcorreia profile image
Rita Correia Author

Thanks Waleed!