Building a Route Search Function with Amazon Location Service

dayjournal

Yasunori Kirimoto

Posted on October 25, 2021

Building a Route Search Function with Amazon Location Service

img

I built a route search function with Amazon Location Service 🎉

Amazon Location Service is a service for building location-based applications within AWS. At present, five types of functions are available: map display function, address search function, route search function, geofence function, and tracking function. This time, I added a route search function and built a map application!

Advance Preparation

  • Amazon Location Service settings up to the map display function

This is a continuation of the previous article I wrote.

Building a Map Application with Amazon Location Service, MapLibre GL JS, AWS Amplify, and Vue.js

Configure Amazon Location Route calculators

First, configure the Amazon Location Route calculators in the AWS console.

Click on "Route calculators".
img

Click "Create route calculator".
img

Enter the route search name and select the data to be used. This time, we chose "SampleRoute".
img

Click on the created route calculator.
img

Copy the "Name" and "ARN" displayed here to use them in future settings.
img

This completes the configuration of Amazon Location Route calculators 👍

Frontend

Next, let's build the map application.

Once you have configured the map display function of Amazon Location Service, you only need to change "MapPane.vue".

execution environment

  • node v16.3.0
  • npm v7.15.1

Install the AWS SDK for JavaScript package in advance.

npm install aws-sdk
Enter fullscreen mode Exit fullscreen mode

Overall composition

img

package.json

{
  "name": "amazon-location-app",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "@aws-amplify/ui-vue": "^1.0.12",
    "aws-amplify": "^4.1.1",
    "aws-sdk": "^2.935.0",
    "core-js": "^3.6.5",
    "maplibre-gl": "^1.14.1-rc.2",
    "vue": "^2.6.11",
    "vue-router": "^3.2.0",
    "vuetify": "^2.4.0",
    "vuex": "^3.4.0"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^6.2.2",
    "sass": "~1.32.0",
    "sass-loader": "^10.0.0",
    "vue-cli-plugin-vuetify": "~2.4.1",
    "vue-template-compiler": "^2.6.11",
    "vuetify-loader": "^1.7.0"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {}
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}
Enter fullscreen mode Exit fullscreen mode

/src/components

MapPane.vue

<template>
    <div class='mapPane'>
        <div id='map'></div>
    </div>
</template>

<script>
    import maplibregl from 'maplibre-gl'
    import { Auth, Signer } from 'aws-amplify'
    import awsconfig from '../aws-exports'
    import Location from 'aws-sdk/clients/location'
    let map;

    export default {
        name: 'MapPane',
        data() {
            return {
                credentials: null,
                client: null,
                params: null,
            }
        },
        mounted: async function () {
            this.credentials = await Auth.currentCredentials()
            this.mapCreate()
            this.addRouteSearch()
        },
        methods: {
            mapCreate: function() {
                map = new maplibregl.Map({
                    container: 'map',
                    style: 'sample',
                    center: [139.7648, 35.6794],
                    zoom: 15,
                    bearing: 64.8,
                    pitch: 60,
                    hash: true,
                    transformRequest: this.transformRequest,
                });

                map.addControl(new maplibregl.NavigationControl());
            },
            transformRequest: function (url, resourceType) {
                if (resourceType === 'Style' && !url.includes('://')) {
                    url = `https://maps.geo.${awsconfig.aws_project_region}.amazonaws.com/maps/v0/maps/${url}/style-descriptor`
                }
                if (url.includes('amazonaws.com')) {
                    return {
                        url: Signer.signUrl(url, {
                            access_key: this.credentials.accessKeyId,
                            secret_key: this.credentials.secretAccessKey,
                            session_token: this.credentials.sessionToken,
                        }),
                    }
                }
                return { url }
            },
            addRouteSearch : function() {
                this.client = new Location({
                    credentials: this.credentials,
                    region: awsconfig.aws_project_region
                });
                this.params = {
                    CalculatorName: 'SampleRoute',
                    DeparturePosition: [139.7558, 35.6767],
                    DestinationPosition: [139.8160, 35.6830],
                    IncludeLegGeometry: true,
                }
                this.client.calculateRoute (this.params, (err, data) => {
                    const routes = data.Legs[0].Geometry.LineString
                    map.on('load', function () {
                        map.addSource('route_sample', {
                            'type': 'geojson',
                            'data': {
                                'type': 'Feature',
                                'properties': {},
                                'geometry': {
                                    'type': 'LineString',
                                    'coordinates': routes
                                }
                            }
                        });
                        map.addLayer({
                            'id': 'route_sample',
                            'type': 'line',
                            'source': 'route_sample',
                            'layout': {
                                'line-join': 'round',
                                'line-cap': 'round'
                            },
                            'paint': {
                                'line-color': '#FF0000',
                                'line-width': 10,
                                'line-opacity': 0.5
                            }
                        });
                    });
                })
            }
        }
    }
</script>

<style scoped>
    #map {
        z-index: 0;
        height: 800px;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

Load the Amazon Location Service.

import Location from 'aws-sdk/clients/location'
Enter fullscreen mode Exit fullscreen mode

Configure the Amazon Location Service and route search settings, specifying the "Name" of the route search you created in CalculatorName. This time, set the start and endpoints to the Tokyo Station area.

this.client = new Location({
    credentials: this.credentials,
    region: awsconfig.aws_project_region
});
this.params = {
    CalculatorName: 'SampleRoute',
    DeparturePosition: [139.7558, 35.6767],
    DestinationPosition: [139.8160, 35.6830],
    IncludeLegGeometry: true,
}
Enter fullscreen mode Exit fullscreen mode

Use Amazon Location Route calculators to draw the route search results on a map.

this.client.calculateRoute (this.params, (err, data) => {
    const routes = data.Legs[0].Geometry.LineString
    map.on('load', function () {
        map.addSource('route_sample', {
            'type': 'geojson',
            'data': {
                'type': 'Feature',
                'properties': {},
                'geometry': {
                    'type': 'LineString',
                    'coordinates': routes
                }
            }
        });
        map.addLayer({
            'id': 'route_sample',
            'type': 'line',
            'source': 'route_sample',
            'layout': {
                'line-join': 'round',
                'line-cap': 'round'
            },
            'paint': {
                'line-color': '#FF0000',
                'line-width': 10,
                'line-opacity': 0.5
            }
        });
    });
})
Enter fullscreen mode Exit fullscreen mode

Configure Amplify roles

Finally, add the Amazon Location Route calculators policy to the Amplify role.

Search for the role that is used for the login function. Select "amplify-xxxxx-authRole".

img

Click "Add Inline Policy".

img

Select "JSON" to set the policy, and set the "ARN" of the map you created to "Resource."

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Routes",
            "Effect": "Allow",
            "Action": "geo:CalculateRoute",
            "Resource": "arn:aws:geo:us-west-2:xxxxx:route-calculator/SampleRoute"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

img

This completes the role configuration for Amplify 👍

Let's check with a simple local server.

npm run serve
Enter fullscreen mode Exit fullscreen mode

Startup a local server and try logging in. You can now see the Amazon Location Route calculators 💡

img

I was able to build a route search function with Amazon Location Service 👍

Using Amazon Location Service, I confirmed that it is easy to build a route search. There are various options available, so I hope you will try them out using this sample as a reference. I will continue to explore other functions as well 💪

💖 💪 🙅 🚩
dayjournal
Yasunori Kirimoto

Posted on October 25, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related