Make a running tracker with Geolocation API

Anthony Ng
Geek Culture
Published in
7 min readJun 1, 2021

--

Release the power of your mobile phone with Web API and Javascript

Location service is a crucial capability of mobile devices. While enjoying all the advantages like direction service, checking the nearest inventory during online shopping, I am always concerned about how much and how detailed my data is collected. Using a VPN or turning off location service is insufficient to completely protect our identity and cause lots of hassle.

Today we will explore how to use the Web API to access the geolocation and get rid of being tracked by tech providers.

Long story short, let’s watch our final product. This demo was running in Safari on iPhone X. Or if you can’t wait, try it on your phone here. 👈

If you can’t load the app, please check out the browser compatibility here.

Table of Content

  1. How to get geolocation
  2. The tracking formula
  3. Map view
  4. Map tile
  5. Update map
  6. Start/ pause button
  7. Log viewer
  8. Wiring up components
  9. Roundup

Real-time geolocation is the meat of the app. We will first learn the orchestration of the bits and bytes. Next, we will explore how to make practical use by playing around with the configuration.

A map view is the core presentation of the app. We will go through the setup of the map, drawing the tracked path and the current location.

To ease the experiment, we will build a real-time log viewer to make a more profound sense of the mechanics.

Lastly, we will build an event-based mechanism to glue up parts for the sake of performance and maintainability.

How to get geolocation?

We will leverage the Geolocation.watchPosition() API to request GPS data. This function is implemented as an observer pattern. When watchPosition() has executed, it will keep listening to a new event. We receive the event in the first argument, i.e. success. If the API fails to locate the coordinate, it calls the second argument, error. Both success and error are expected as a callback function to handle the individual situation.

If the browser supports geolocation API [line 2], we will start watchPosition() by passing arguments success, error, and trackOptions. We will discuss trackOptions in a moment.

The tracking formula

It is a tradeoff between the sampling frequency and data accuracy. By default, it allows an infinity response time to get precise data. This setting favour application required high precision and latency is not a priority. A runner would expect a new coordinate to be recorded at a sensible frequency in our running tracker, e.g. every 2–5 seconds. A lower precision of data is acceptable as we care about the entire path rather than a single point. Hence, we dedicatedly configured trackOptions to have frequency over accuracy as a preference.

The trackOptions comprise parameters enableHighAccuracy, maximumAge, and timeout.

enableHighAccuracy is a boolean value to switch the modes between more accurate and use more power and less accurate and use less power. We will enable it in the tutorial as power consumption is not our primary concern.

timeout determines the frequency to obtain a new position. The default value of timeout is infinity, meaning it will return when the device successfully get the new coordinate. We will override this value to 5 seconds in our case to experience an eagerly updated path and distance meter.

If a new coordinate is not available when it reaches the timeout, it will use the cached value. Parameter maximumAge guarantees the coordinate is not too outdated. If the cached value is older than the maximumAge, it will look for a new reading. In our case, we use 30 seconds as the maximumAge to keep the user experience smooth.

Map view

To stay away from the technologies designed to collect geolocation data and user identity, I used an open-source library leaflet.js in this project. Leaflet.js generate map view in browsers, with layers of geographical information received from the GPS chips in mobile phones. No geolocation data is being sent to any backend server.

We will create a full-screen map view [line 6], import leaflet.css [line 9] and leaflet.js [line 16], as well as our custom logic tracker.js [line 30] and tracker.css[line 22]. Then, a <div> specified with id='tracker' is added [line 28] as a placeholder for the tracker.

When the app (literally the URL) is loaded, users will see a landing page that shows the default map. I will use the London centre in the tutorial, but you might change to wherever you want. The L object is the Leaflet functions entrance. We can associate the view with the div with the id tracker we’ve just defined. Next, we locate the focus to the London centre and pass a zoom level of 13, showing fewer details but broader coverage.

Map tile

To display a geographical region on a map, we need a map provider.

We will use Mapbox as it offers a free tier service for small volume use. To use it,

  1. register a Mapbox account,
  2. create an API_KEY with scope to the URLs of the website.
  3. copy the code followed and replace YOUR_API_KEY with yours.

Update map

When a new geolocation event pop out, we will repeat three steps:

  1. extend the path segment to the new position
  2. relocate the current marker
  3. refresh the distance meter

To make sure the steps happen in sequence and for the sake of Clean Code, we organise the three steps as a function chain using Promise.

Draw new Segment

To initialise the first path segment, beware of passing an array of latlng array to L.polyline() [line 8]. Next, we will pin the default London map view at the first coordinate we detect, and zoom in to level 15 by map.setView()[line 15]. Then we use map.fitBounds() to adjust to a comfortable view [line 16].

Refresh distance meter

The meter accumulates the distance of segments and updates the <div> with id distance-box. We will base on the formula provided by geoDatasource.com.

Start/ pause button

We will create a switch to start the tracking if users are ready to start the trip. The watchPosition() start the surveillance until the web page is closed. If a user wants to take a break and not plot the locations on the map, he/ she can switch it off.

Log viewer

When I started working on this project, a pretty much time was in testing, where I travelled around the town and bought it along with my jogging. I created a log viewer using a semi-transparent overlay effect for trouble-shooting and configuration tuning. I keep this feature as it looks fantastic, and it will be helpful when we extend more functions.

Wiring up components

We’ve got the success callback function that will be triggered when geolocation is received. We also have the updateMap function that manages the graphical work on the map. It is the time to glue up both.

The most straightforward way is to call updateMap in success function. However, there are two drawbacks. First, in a multi-tasking browser environment, longer function chains are easier to suffer by being less responsive. Second, it is less flexible to change in the sense of maintenance.

Therefore, we are going to decouple it by adopting an event-driven manner.

Publisher

The success callback function acts as a publisher to dispatchEvent()[line 22]. The publisher is responsible for placing the event in a queue served by somebody, but it doesn’t care who it is. Hence the success function is lightweight and responsive.

Subscriber

The subscriber, attached to the <div> with id tracker, serves the queue by sending the very first event to updateMap() [line 26].

The beauty of this approach is to distribute loading to the queue and free both the success and updateMap function from overloading.

Are you excited to go jogging? Let’s wrap up before you leave the door.

Roundup

Today we have walked through a basic but complete solution to build a running tracker web app working in browsers. Although the purpose is more on exploring the Web API, we enjoy the benefits right away by getting rid of the tracking by the cloud providers, using a map in real-time without exposing personal identities, and most importantly, it is free and fun.

The Web Geolocation API is indeed a great place to start with if you want to turn your mobile phones into IoT devices at no cost.

Most popular browsers widely support the web geolocation API on Android and iOS, which is merit over native SDK if we deal with geographical problems. The downside is that only latitude and longitude are available, although other properties such as direction and speed are defined in the interface.

It is impressive that the API work with low/ no Internet connection when I tried to turn off mobile data during the tests. However, it is limited by real-time map API that failed to update the map tile when my location was outside the current tile. It will be exciting to explore further if we replace the map API with an offline map solution.

Thank you for reading ❤️. I hope you enjoy this sharing.

Demo 🏃

Complete source code 🔥

If you are interested in my other article, please visit my blogs on Medium.

--

--