Part 1. Building a Location Tracker with OpenLayers

Photo by Z on Unsplash

Part 1. Building a Location Tracker with OpenLayers

This is a simple OpenLayers application that tracks a device's location and displays it on a map.

Brian Omondi's photo
·

5 min read

Location tracking is a common feature in many applications, and in this tutorial, we'll explore how to create a simple location tracker using the OpenLayers library. OpenLayers is a powerful open-source JavaScript library for displaying maps on the web.

Prerequisites

Before we begin, ensure you have a basic understanding of HTML, JavaScript, and web development. Also, ensure that you have a code editor of your choice installed and Nodejs.

Setting Up the Project

Let's start by creating the basic structure of our project. Create the following files in your project directory and initialize npm in your project directory

  • index.html

  • index.js

  • style.css

mkdir locator && cd locator

npm init -y

touch index.html index.js style.css

We'll install the required dependencies, OpenLayers, vite and idb.

OpenLayers is an open-source JavaScript library used to create interactive web maps. It's like a toolkit for developers to easily build powerful map applications without complex server-side setup.

npm install ol

Vite is a modern frontend build tool designed to provide a faster and leaner development experience for building web applications

npm install -D vite

This should do it for the project set-up. Let's start coding!

Layout and Styling

Add the code below to your index.html file.

<html lang="en">
  <head>
     <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Locator</title>
    <link href="./style.css" rel="stylesheet" />
  </head>
  <body>
    <!-- Map container and locate button -->
    <div id="map"></div>
    <button id="locate" title="Locate">
      <i class="fas fa-location-arrow"></i>
    </button>
    <!-- Include the OpenLayers library and index.js -->
    <script type="module" crossorigin src="./index.js"></script>
  </body>
</html>

The <div id="map"></div> is a container for the map. This is where the OpenLayers map will be displayed.

The <button> with ID "locate" serves as a button to trigger the location-tracking functionality. It contains an <i> tag with the class "fas fa-location-arrow" to display a location arrow icon. It's a violation to trigger location tracking without a user gesture.

The final <script> tag imports the main JavaScript file (./index.js). The type="module" attribute indicates that this script is an ECMAScript module.

Add the following code to your style.css file.

@import url("./node_modules/ol/ol.css");
@import url("https://use.fontawesome.com/releases/v5.0.13/css/all.css");

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html,
body {
  height: 100%;
  width: 100%;
  scroll-behavior: smooth;
}

#map {
  height: 100%;
  width: 100%;
}

button {
  background-color: #000;
  position: absolute;
  bottom: 20px;
  right: 20px;
  padding: 18px;
  border: none;
  border-radius: 100%;
  color: aliceblue;
}

Creating the OpenLayers Map

In this step, we'll be adding the logic for adding the map to or web page.

Initialize OpenLayers

Open the index.js file and the code below.

import { Map, View, Feature } from "ol";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { transform } from "ol/proj";
import { OSM, Vector as VectorSource } from "ol/source";
import { Point, LineString } from "ol/geom";

/**
 * @type {Map}
 */
let map;

/**
 * @type {View}
 */
let view;

let coordinates = [];

/**
 * @type {VectorLayer}
 */
let markerLayer;


const init = () => {
    view = new View({
        center: [0, 0],
        zoom: 2,
    });


    map = new Map({
        target: "map",
        layers: [
            new TileLayer({
                source: new OSM(),
            })
        ],
        view: view,
    });

    document.getElementById("locate").addEventListener("click", (e) => {
        e.preventDefault();
        locate();
    });
};

const addMarker = (coord) => {
    if (coordinates.length < 2 || !markerLayer) {
        markerLayer = new VectorLayer({
            source: new VectorSource({
                features: [
                    new Feature({
                        geometry: new Point(coord),
                    }),
                ],
            }),
        });

        map.addLayer(markerLayer);
    } else {
        markerLayer.getSource().clear();
        markerLayer.getSource().addFeature(
            new Feature({
                geometry: new Point(coord),
            })
        );

        markerLayer.getSource().addFeature(
            new Feature({
                geometry: new LineString(coordinates),
            })
        );
    }

    view.animate({
        duration: 2000,
        center: coord,
        zoom: 18,
    });
}


const locate = () => {
    if (navigator.geolocation) {
        navigator.geolocation.watchPosition(
            (position) => {
                let { latitude, longitude } = position.coords;
                const coords = transform(
                    [longitude, latitude],
                    "EPSG:4326",
                    "EPSG:3857"
                );
                coordinates.push(coords);

                addMarker(coordinates[coordinates.length - 1]);
            },
            console.error,
            {
                enableHighAccuracy: true,
                maximumAge: 5,
            }
        );
    }
};

window.onload = init;

In this code block, we create OpenLayers View with an initial centre and zoom level. The Map is then instantiated with a target element - map, layers (in this case, an OpenStreetMap layer), and the defined view.

The addMarker function is responsible for adding markers to the map based on the user's location. It also handles the creation of a line connecting consecutive markers to visualize the movement: If there are fewer than two coordinates or if the marker layer hasn't been initialized yet, if true, it creates a new marker layer and adds a point feature to it. Otherwise, it updates the existing marker layer with the latest point and a line feature connecting the points.

The locate function utilizes the Geolocation API to continuously watch for the user's position. When a new position is obtained, it transforms the coordinates and updates the marker on the map using the addMarker function.

Running the project

In your terminal type the command below to start the dev server.

npm run dev

This will run the app on port 5173 - Vite's default port. Navigate to https://localhost:5173 to view the app.


Congratulations! You've successfully built a simple location tracker using OpenLayers. In this tutorial, we explored how to set up a basic project structure, create an interactive map, and implement location tracking. In the next series, we'll be handling offline support and analysis using indexedDB

Feel free to expand on this project by adding additional features or customizing the user interface. Happy coding!

Link to the Github repository <https://github.com/bryanbill/locator\>