How to use Azure Maps to Build a Taxi Hailing Web App

This post has been republished via RSS; it originally appeared at: Microsoft Tech Community - Latest Blogs - .

How to use Azure Maps to Build a Taxi Hailing Web App

Learn how simple it is to set up an Azure Maps Resource account and quickly create applications that have beautiful maps that can be used in a range of solutions. In this tutorial we are going to create a simple and fast taxi hailing Web application with only HTML, CSS and Vanilla JavaScript.

 

The Taxi Hailing Web Application

Roam Rides is a fictional company that wants to extend their static web application to have capability to offer route calculation and generate a price for a trip that must be made in that calculated route. In this tutorial we are going to add basic map functionalities and features using a CDN link that loads the Azure Maps SDK into our project.

theophilusO_0-1703212309469.png

 

What you will need

Create an Azure Maps Account

  1. Head over to  Azure portal.
  2. In the search box, type in Azure Maps then select Azure Maps Accounts as show in the picture below.

theophilusO_1-1703212309475.png

 

  1. Select + Create and in the Create an Azure Maps Account resource page create a new resource group or use a preferred resource group, enter name of the Azure Maps Resource you want to create, for example I will name the resource Roam, the name should be unique.
  2. Click Review + Create.
  3. After the deployment is done select Go to resource and on the left panel select Authentication and copy the Primary Key.

theophilusO_2-1703212309485.png

 

 

Build the Taxi Hailing Website and Add Azure Maps Map Control

This section introduces you to Azure Maps Map Control and gives you guidance on how you can directly use Azure Maps SDK CDN to start practicing and build an applications with Azure Maps in a fast, clean and easy way, just to get your feet wet. To show you this, we are going to build a taxi hailing app. To get all the code we are going to use for this tutorial, feel free to fork the repository azureMaps-roamrides from GitHub.  

  1. Create an index.html, index.css, map.js and index.js file.
  2. In the index.html file add the following html code.

 

The html head code

 

 

<!DOCTYPE html>

<html>

<head>

    <title>Roam Rides</title>

    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">



    <!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->

    <link rel="stylesheet" href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.css" type="text/css">

    <script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.js"></script>



    <!-- Add a reference to the Azure Maps Services Module JavaScript file. -->

    <script src="https://atlas.microsoft.com/sdk/javascript/service/2/atlas-service.min.js"></script>

    <script src="map.js"></script>

    <link rel="preconnect" href="https://fonts.googleapis.com">

    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

    <link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=MuseoModerno:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Open+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,300;1,400;1,500;1,600;1,700;1,800&display=swap" rel="stylesheet">

    <link rel="stylesheet" href="index.css">

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">

</head>

 

 

Notice the SDK files we have just imported into the project:

 

 

 <!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
<link rel="stylesheet" href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.css" type="text/css">
<script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.js"></script>
<!-- Add a reference to the Azure Maps Services Module JavaScript file. -->
<script src="https://atlas.microsoft.com/sdk/javascript/service/2/atlas-service.min.js"></script>

 

 

We first of all add references to the css style sheet of the map, which is a CDN link. We then add a global version of the Web SDK which is also served as a CDN.

  1. We then add a reference for map.js as <script src="map.js"></script>, in order for it to be loaded first.
  2. Add the rest of the html code shown below.
    <body>
        <div class="main-container">
            <div class="input-container">
                <div class="heading">
                    <h1>Roam Rides</h1>
                    <p>Get a ride to your destination.</p>
                </div>
                <div class="ad-label" id="ad-label-box">
                    <p> <i class="fa fa-car-side"></i> let's go</p>
                </div>
                <div class="inputs-box">
                    <div class="top-form-section">
                        <div class="input-section">
                            <label for="start">Pick up Street</label>
                            <br>
                            <input list="start-locations-list" type="text" name="start" id="start-location" placeholder="e.g. Harambee Avenue">
                            <datalist id="start-locations-list">
                            </datalist>
                        </div>
                        <div class="input-section">
                            <label for="start">Drop of Street</label>
                            <br>
                            <input list="end-locations-list" type="text" name="end" id="end-location" placeholder="e.g. Upper Hill Nairobi">
                            <datalist id="end-locations-list">
                            </datalist>
                        </div>
                    </div>
                    <div class="buttons-container">
                        <button onclick="GetMap()">Get Ride</button>
                    </div>
                </div>
                <div class="result-container" id="res-container">
                </div>
            </div>
            <div id="myMap"></div>
        </div>
    <script src="index.js"></script>
    </body>
    </html>​
  3. Next let’s add some code to map.js.

 

The following code creates a GetMap() function that will create a map object.

let map, datasource, client;

 

 

function GetMap(){
            //Instantiate a map object
    var map = new atlas.Map('myMap', {
// Replace <Your Azure Maps Key> with your Azure Maps subscription key. https://aka.ms/am-primaryKey
        authOptions: {
        authType: 'subscriptionKey',
        subscriptionKey: '<key in your primary subscription key here'
        }
    });
}

 

 

We then add this section to the function, this part of the code will create a data source and add map layers only when all resources are ready and have been all loaded.

 

 

//Wait until the map resources are ready.
    map.events.add('ready', function() {
    //Create a data source and add it to the map.
    datasource = new atlas.source.DataSource();
    map.sources.add(datasource);

    //Add a layer for rendering the route lines and have it render under the map labels.
    map.layers.add(new atlas.layer.LineLayer(datasource, null, {
        strokeColor: '#b31926',
        strokeWidth: 5,
        lineJoin: 'round',
        lineCap: 'round'
    }), 'labels');

    //Add a layer for rendering point data.
    map.layers.add(new atlas.layer.SymbolLayer(datasource, null, {
        iconOptions: {
            image: ['get', 'icon'],
            allowOverlap: true
    },
        textOptions: {
            textField: ['get', 'title'],
            offset: [0, 1.2]
        },
        filter: ['any', ['==', ['geometry-type'], 'Point'], ['==', ['geometry-type'], 'MultiPoint']] //Only render Point or MultiPoints in this layer.
    }));

 

 

In this other section, still under the GetMap() function, we are going to pick out the latitude and longitude from the input boxes that we have in the html document. The split method in JavaScript will be used to derive the coordinates from the input boxes. We can finally calculate the route and find necessary information.

 

 

//Create the GeoJSON objects which represent the start and end points of the route.
    //starting coordinates
    let start_lat=parseFloat(startLocation.value.split(':')[1].split(',')[0])
    let start_long=parseFloat(startLocation.value.split(':')[1].split(',')[1])
    var startPoint = new atlas.data.Feature(new atlas.data.Point([start_long,start_lat]), {

        title: `${startLocation.value.split(':')[0]}`,
        icon: "pin-red"
    });
    //destination coordinates

    let end_lat=parseFloat(endLocation.value.split(':')[1].split(',')[0])
    let end_long=parseFloat(endLocation.value.split(':')[1].split(',')[1])
    var endPoint = new atlas.data.Feature(new atlas.data.Point([end_long,end_lat]), {

        title: `${endLocation.value.split(':')[0]}`,
        icon: "pin-round-red"
    });

//Use MapControlCredential to share authentication between a map control and the service module.
    var pipeline = atlas.service.MapsURL.newPipeline(new atlas.service.MapControlCredential(map));
    //Construct the RouteURL object
    var routeURL = new atlas.service.RouteURL(pipeline);
    //Start and end point input to the routeURL
    var coordinates= [[startPoint.geometry.coordinates[0], startPoint.geometry.coordinates[1]], [endPoint.geometry.coordinates[0], endPoint.geometry.coordinates[1]]];
    //Make a search route request
    routeURL.calculateRouteDirections(atlas.service.Aborter.timeout(10000), coordinates).then((directions) => {
        //Get data features from response
        var data = directions.geojson.getFeatures();
        datasource.add(data);
    });
    });

 

 

  1. Lastly, we add to the GetMap() function the following code. This code will create date formatter for your local region to display information on the pick up and drop off time. Finally it then appends the data and information of that route requested. How it does this? We use fetch API to get response from the Azure server that will serve us with the route calculation result. You can use Postman to test for some of these endpoints that have been shared in the code.

 

 

//create time formatter

    // Create a formatter with options for 12-hour clock system

    const formatter = new Intl.DateTimeFormat('en-US', {

        hour: 'numeric',

        minute: 'numeric',

        second: 'numeric',

        hour12: true

    });

    //route calculation result container & pricing container

    const res_routBox=document.getElementById('res-container')

    const pricing_container = document.getElementById('ad-label-box')

    //get route calculation details

    fetch(`https://atlas.microsoft.com/route/directions/json?subscription-key=<subscription_key>&api-version=1.0&query=${startLocation.value.split(':')[1]}:${endLocation.value.split(':')[1]}`)

    .then(response => response.json())
    .then(route =>{
      if((parseFloat(route.routes[0].summary.travelTimeInSeconds)/60).toFixed(0)>=60){

            route.routes[0].summary.travelTimeInSeconds = `${(parseFloat(route.routes[0].summary.travelTimeInSeconds)/3600).toFixed(0)} Hrs`

        }else{

            route.routes[0].summary.travelTimeInSeconds = `${parseFloat((route.routes[0].summary.travelTimeInSeconds)/60).toFixed(0)} mins`

        }
        if((parseFloat(route.routes[0].summary.trafficDelayInSeconds)/60).toFixed(0)>=60){

            route.routes[0].summary.trafficDelayInSeconds = `${(parseFloat(route.routes[0].summary.trafficDelayInSeconds)/3600).toFixed(0)} Hrs`

        }else{

            route.routes[0].summary.trafficDelayInSeconds = `${parseFloat((route.routes[0].summary.trafficDelayInSeconds)/60).toFixed(0)} mins`

        }
        res_routBox.innerHTML=
        <div class="result-card">
            <h1>${(parseFloat(route.routes[0].summary.lengthInMeters)/1000).toFixed(0)}Km</h1>
            <p><i class="fa fa-car"></i></p>

        </div>
        <div class="result-card">
            <h1>Hailed at</h1>
            <p><i class="fa fa-person-circle-plus"></i> ${formatter.format(new Date(route.routes[0].summary.departureTime))}</p>

        </div>

        <div class="result-card">
            <h1>Drop off time</h1>
            <p><i class="fa fa-person-walking"></i> ${formatter.format(new Date(route.routes[0].summary.arrivalTime))}</p>
        </div>

        <div class="result-card">
            <h1>Duration</h1>
            <p><i class="fa fa-stopwatch"></i> ${ route.routes[0].summary.travelTimeInSeconds}</p>
        </div>
        <div class="result-card">
            <h1>Traffic time</h1>
            <p><i class="fa-regular fa-clock"></i> ${(parseFloat(route.routes[0].summary.trafficDelayInSeconds)/60).toFixed(0)}min</p>
        </div>

        // $0.1885/km, & $0.028/min - theses are my pricing table values

        pricing_container.innerHTML = `<p> <i class="fa fa-wallet"></i> Trip cost <i class="fa fa-arrow-right"></i> $ ${(((parseFloat(route.routes[0].summary.lengthInMeters)/1000)*0.1885)+((parseFloat(parseInt(route.routes[0].summary.trafficDelayInSeconds)/60))*0.028)).toFixed(2)}</p>`

    })

 

 

  1. Now add the CSS code found in the repository to the index.css file you created.
  2. To add functionality to the app, also add the JavaScript code found in the repository to your index.js file.

 

The following JavaScript code utilizes fetch api to suggest locations while typing into the text boxes. The getLocations() function does the job of getting this locations through the help of fetch api, that utilizes the end point specified above that returns a number of results as a response. The getLocations() function then appends these results to the data list specified as <option/> elements.

  1. Now our last step is to open the index.html page and see if the web app works. If it works, it supposed to look like the one shown in the screenshot below.

 

theophilusO_3-1703212309489.png

 

  1. Type in a pick up street and a drop street and observe let’s go label change to pricing.

There we have it. You have successfully helped Roam Rides to achieve their goal. Congratulations on implementing Azure Apps on a web application.


Learn More Here

How to use Azure Maps with Node.js npm Package

Use Azure Maps Map Control

Changing Map Styles

Azure Maps Documentation

Create an Android App with Azure Maps

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.