Build Different

Add Live Traffic Data to Your Site in 5 Minutes

Ruanna Owens
Jul 12, 2022 • Last edit on Jul 13, 202210 min read
Three screens displaying live traffic data from TomTom

Displaying real-time traffic data has many benefits, ranging from early safety alerts to establishing the most effective route for commuters to determining exact journey times and projections for delivery and on-demand services.

In the past, we had to listen to radio stations or wait for someone to report any traffic accidents on our path. Now, we can find the most efficient route based on data from other users, thanks to real-time data sharing.

TomTom APIs use anonymized, real-time data from GPS devices all over the world to provide a live view with helpful traffic information. We can easily add live traffic data to our website with TomTom Maps. This tutorial will show how to do this in five minutes.

Sound good? Let’s start!

Prerequisites

To follow this, ensure you have:

  • Basic knowledge of HTML and CSS.
  • B basic knowledge of React Native and JavaScript.
  • Node.js and npm installed on your local development machine.

Project Setup

It’s free and simple to use TomTom Maps SDK. You must first create a TomTom Developer Portal account to obtain an API key. This key grants you access to TomTom’s services, which instantly appears on your dashboard when you sign in.

Creating a React App

Let’s start by creating a new React project. This demonstration uses Vite, but you’re welcome to use your bundler of choice, like Vite or Create React App (CRA), for example.

# vite
npm init vite@latest live-traffic-maps --template react
# create react app
npx create-react-app live-traffic-maps

Once it’s finished, run:

cd live-traffic-maps
npm install

If you’re adding TomTom Maps to an existing React app, skip this step and install the TomTom Maps SDK.

Installing TomTom’s Tools

To install TomTom Maps SDK, navigate to the app’s root directory, and run the following command:

npm i @tomtom-international/web-sdk-maps

TomTom Services SDK provides the search API we use in this article, so install it using the command:

npm i @tomtom-international/web-sdk-services

Adding a TomTom Map

To add a TomTom map, first, we must import the TomTom Maps JavaScript SDK and the default map stylesheet.

In the App.js component, add the following code:

1import "./App.css";
2import "@tomtom-international/web-sdk-maps/dist/maps.css";
3import * as ttmaps from "@tomtom-international/web-sdk-maps";

Now, we also import React Hooks, namely useRef, useEffect, and useState, into the app.

import { useRef, useEffect, useState } from "react";

useRef helps to manipulate the DOM directly within React by holding a reference to the actual (non-virtual DOM) element. We use it to add our map during the initial loading of the site:

const mapElement = useRef();

We use the useState hook to hold the variables used in this app. With the hook, we initialize the app’s values that we want to preserve.

Starting at the top, we set the state variable map, which has a reference to the TomTom map object we create.

Set the map’s initial longitude and latitude to null because the position of the map will depend on the user’s location.

Following that, we define the state variables that handle the result object we get back after sending the query:

1const [map, setMap] = useState({});
2const [mapLongitude, setMapLongitude] = useState(null);
3const [mapLatitude, setMapLatitude] = useState(null);
4const [query, setQuery] = useState("");
5const [result, setResult] = useState({});

Next, we use the useEffect hook to initialize the map. This is the key to making our TomTom map work seamlessly with React. It runs after the component mounts, calling the TomTom Maps Web SDK’s tt.map function to create our map.

Inside the functional component App, add the following code:

1useEffect(() => {
2 let map = ttmaps.map({
3 key: "<Your API Key>",
4 container: "map-area",
5 center: [mapLongitude, mapLatitude],
6 zoom: 15,
7 pitch: 50,
8 style: {
9 map: "basic_main",
10 poi: "poi_main",
11 trafficFlow: "flow_relative",
12 trafficIncidents: "incidents_day",
13 },
14 stylesVisibility: {
15 trafficFlow: false,
16 trafficIncidents: false,
17 },
18 });
19 setMap(map);
20 return () => {
21 map.remove();
22 };
23}, []);

We created a map instance by calling the TomTom Maps SDK’s tt.map function. Then, we passed an options object to the method containing the following properties:

  • key — Your API Key, accessed in the developer dashboard.
  • container — The container to which we attach the map, defined with useRef.
  • center — The initial focus and the center point of the map.
  • zoom — The initial zoom level of the map.
  • pitch — The tilt level of the map.
  • style — The map style. Here, we pass in a configuration object containing the default styles. However, there are also many alternative styles you can use.
  • styleVisibility — Contains the options representing visibility of style parts. Here, we set the trafficFlow and trafficIncidents options to false, so we can toggle the style visibility on and off in the UI by setting them to true or false.

Next, we will obtain the user’s GPS coordinates using the Geolocation API. This will be done immediately after the map has been created. To do this, we use the useEffect hook since it works exactly like the componentDidMount lifecycle method. Here’s the code:

1useEffect(() => {
2 navigator.geolocation.getCurrentPosition(
3 (position) => {
4 setMapLongitude(position.coords.longitude);
5 setMapLatitude(position.coords.latitude);
6 },
7 (error) => {
8 alert(error.message);
9 }
10 );
11 }, []);

By using the geolocation.getCurrentPosition method, our app will prompt the user to give access to their location. If the user grants permission, the state gets updated and the user’s GPS coordinates get saved. If the user declines permission, then it will display an error message.

Now that we have the user’s coordinates saved, we will display that location on the map. Using another useEffect, but this time, representing a componentDidUpdate lifecycle method, we can set the center of the map to the user’s location.

1useEffect(() => {
2 if (mapLongitude && mapLatitude) {
3 map.setCenter([mapLongitude, mapLatitude]);
4 }
5 }, [mapLongitude, mapLatitude]);

By placing the mapLongitude and mapLatitude in the dependencies array, the map’s center gets updated anytime the user changes their current location.

Finally, add the following code to render the map. It defines a layout in which to place the map.

<div ref={mapElement} id="map-area"></div>

Now, a bit of styling to define the height and width of the map container:

1#map-area {
2 height: 90vh;
3 width: 100%;
4}

Then, run the app using the command:

#vite
npm run dev
#Create react app
npm start

In the browser, you’ll see a popup asking for permission. If you choose to share your location, you will see a map similar to this:

Photo1

Adding Search Functionality

We can use TomTom’s Search API to find a location through a process called geocoding, which means that we’re turning the description of a location into coordinates on a map.

We do this by adding the default fuzzy search option, which performs a search for a partial match and extends a query result by adding near-match entries and nearby points of interest (POIs).

This works by calling a fuzzySearch function, which returns a list of coordinates that correspond to the given address query.

Begin by adding the following code to import the services library. This step is important as it gives us access to the Search API.

import tt from "@tomtom-international/web-sdk-services";

Now, in the functional component, we create a function called fuzzySearch to handle the search logic:

1const fuzzySearch = (query) => {
2 tt.services
3 .fuzzySearch({
4 key: "<Your API Key>",
5 query: query,
6 })
7 .then((res) => {
8 const amendRes = res.results;
9 setResult(amendRes);
10 moveMapTo(res.results[0].position);
11 })
12 .catch((err) => {
13 console.log(err);
14 });
15};

In the code above, we called the fuzzySearch API method, passing in the API key and the query (the query being the location the user searches).

The fuzzySearch method returns an object containing several properties related to the search query. The results property will then hold an array of locations returned from the search.

When the response is ready, we assign the results — res.results — from the query to the result state using setResult. Then we call the moveMapTo method, passing in the position property of the first match.

The moveMapTo function handles the moving of the app to the search location:

1const moveMapTo = (newLoc) => {
2 map.flyTo({
3 center: newLoc,
4 zoom: 14,
5 });
6};

Here, the map moves from the current location to the location that matches the search query best. So, when the user searches for a location, the map moves to the new location with a smooth animation.

Use the jumpTo method if you want the map to update without an animated transition.

Then, using the map function, we loop through the search results and display them in the UI. If there are no results for the searched location, it displays “No locations.”

1{
2 result.length > 0 ? (
3 result.map((resultItem) => (
4 <ResultBox result={resultItem} key={resultItem.id} />
5 ))
6 ) : (
7 <h4>No locations</h4>
8 );
9}

Within the function scope, we define the ResultBox component, which represents each individual result:

1const ResultBox = ({ result }) => (
2 <div
3 className="result"
4 onClick={(e) => {
5 moveMapTo(result.position);
6 setMapLongitude(result.position.lng);
7 setMapLatitude(result.position.lat);
8 }}
9 >
10 {result.address.freeformAddress}, {result.address.country}
11 </div>
12);

In the code above, each result displays the address and country. When clicked, the coordinates are set and the map moves to that specific location.

Displaying the Components

Now, that we’ve set up the search functionality, let’s display the complete app layout. To do this, we return this in the App component:

1return (
2 <div className="App">
3 <div className="control">
4 <h2>Map Controls</h2>
5 <div className="search-wrapper">
6 <div className="search-control">
7 <input
8 className="input"
9 type="text"
10 placeholder="Search Location"
11 value={query}
12 onChange={(e) => {
13 setQuery(e.target.value);
14 }}
15 onKeyPress={(e) => {
16 if (e.key === "Enter") {
17 fuzzySearch(query);
18 }
19 }}
20 required
21 />
22 <button type="submit" onClick={() => fuzzySearch(query)}>
23 Search
24 </button>
25 </div>
26
27 <div className="results">
28 {result.length > 0 ? (
29 result.map((resultItem) => (
30 <ResultBox result={resultItem} key={resultItem.id} />
31 ))
32 ) : (
33 <h4>No locations</h4>
34 )}
35 </div>
36 </div>
37 </div>
38 <div ref={mapElement} id="map-area"></div>
39 </div>
40);

In the code snippet above, we’ve included the search controls, which include input tags and a button to handle the search functionality.

Now, let’s add the following styles into the App.css file:

1.App {
2 display: flex;
3 justify-content: space-around;
4 margin: 1.5rem;
5}
6
7.control {
8 text-align: center;
9 margin-right: 1.5rem;
10}
11
12.search-wrapper {
13 max-width: 100%;
14 background: white;
15 border: 1px solid lightgray;
16 overflow: hidden;
17}
18
19.search-wrapper:hover,
20.search-wrapper:focus {
21 border: 1px solid #ccc;
22}
23
24input {
25 outline: none;
26 font-size: 1rem;
27 border: 1px solid lightgray;
28 padding: 0.5rem;
29 margin: 1rem;
30 border-radius: 15px;
31}
32.search-control {
33 display: flex;
34 justify-content: center;
35}
36
37button {
38 background: #01ac01;
39 border: 1px solid lightgray;
40 color: white;
41 padding: 0.5rem;
42 margin: 1rem;
43 font-size: 1rem;
44 cursor: pointer;
45}
46
47.result {
48 cursor: pointer;
49 text-align: left;
50 padding: 0.5rem;
51 font-size: 0.85rem;
52}
53
54.result:hover {
55 background: whitesmoke;
56}
57
58#map-area {
59 height: 90vh;
60 width: 100%;
61}
62
63/* Responsive Media Queries */
64
65@media screen and (max-width: 800px) {
66 .App {
67 flex-direction: column;
68 }
69
70 .control {
71 margin-right: 0;
72 }
73
74 .result {
75 text-align: center;
76 }
77}
78
79@media screen and (max-width: 400px) {
80 .search-control {
81 display: block;
82 }
83 button {
84 margin: -1rem 0 0.5rem;
85 }
86}

You should have a UI like the image below:

Photo2

App Demo

Now to demonstrate how the app works, let’s search for Ottawa, Canada, Lagos, and Nigeria respectively. The app moves to the location and displays it.

To see the traffic flow on the map, change the stylesVisibility flag, trafficFlow to true. Here’s the resulting UI:

Photo3

To see the traffic incidents on the map, change the stylesVisibility flag, trafficIncidents to true. Here’s the resulting UI:

Photo4

We can also observe that the map automatically changes in real time. See the screenshots below:

Photo5

Photo6

On closer look, we’ll see that within a minute, the traffic flow around the highlighted location turns from yellow to green, indicating a free flow of traffic.

Conclusion

And that’s a wrap! We’ve added an interactive map that shows real-time traffic for the searched area, and demonstrated how easy it is to set up.

By integrating TomTom APIs into your website, you can inform users and visitors on the best route to take to get them to their destination as quickly as possible, based on current traffic conditions.

There’s still a lot you can do using TomTom APIs. For instance, the Routing API can be used to compute road mileage and travel time, as well as visually indicate the best route for a trip.

Learn more about integrating TomTom’s Maps APIs into your websites and applications to manage your fleets, locate vehicles, and track assets on a map in real-time. Sign up for a free developer account today and start using TomTom’s Traffic APIs!

Get the developer
newsletter.

No marketing fuff. Tech content only.
Thanks for contacting us

We will reach out to you soon.
Blog cards
tomtom tech news