Who wants ice cream?! - In this series of blog posts we are going to develop a small web application called "Gelary" using HERE maps and services. Gelary aims to disrupt the ice-cream market by enabling ice-cream producers to deliver their sweet goods directly to their customers, wherever they are.
The final application will resemble a mobile dashboard view for the employees of our little start-up which they can either take on the road or use at Gelary HQ to plan their work. It will consist of a map and a floating control panel behind a menu button. The map is used to visualise a route, starting from the user's current position along a series of customers, and the traffic situation along the route. The control panel will enable our delivery drivers to search for nearby ice cream shops, display turn-by-turn directions as well as to calculate the best pick-up location for a group of selected customers. The app will also be able to handle order changes: e.g. if a customer cancels or updates his or her position, the route will automatically be recalculated.
What will we learn in this tutorial?
In the previous post we've learned how to request the user's physical location via his or her web browser's geolocation API and update the map accordingly. If you haven't read it - we'd recommend to check it out before moving on.
Now it's time to jump into the deep end and get familiar with the routing API. We will start by calculating a route between two locations and draw the result as polyline onto our map. - Ready? Let's dive right in!
Using the RoutingService
HERE's map API provides a class called Platform to facilitate API calls from the client. We've learned how to instantiate it in our first post by passing our API credentials:
In this example we're also able to utilise our platform instance to access the routing service by calling getRoutingService().
Yon can find more information on the routing API in the documentation.
The RoutingService object provides two methods - configure and calculateRoute, the latter being the method we're primarily interested in here. Let's take a closer look!
calculateRoute takes three parameters:
|Parameter ||Description |
|calculateRouteParams ||An object containing search parameters required to query the HERE API for a route, including a list of waypoints and the desired routing mode. |
|onSuccess ||Callback triggered once a route has been successfully returned from HERE’s service. |
|onError ||Callback for the case that the request wasn’t completed successfully. |
Requesting a route
To request a simple route we must first define a start and end point. This information will be passed as WayPointParameterType objects (more information in the documentation). We also need to decide on a routing mode. As our delivery drivers are experts and ice cream doesn't like to stay in the sun too long, let's go with fastest;car in this case. Additionally we use the representation key to define that the response shall be formatted for the use with our map by setting it to display.
Finally we'll need to implement our callbacks - let's start simple by logging the result to the browser's console:
Refresh your browser window and check the console - you should see an entry looking something like this:
Awesome! We're a good step closer to getting our route printed onto the map. Let's keep going!
Keeping our code clean is key to a maintainable codebase. So let's give the routing functionality a bit of structure and move it into it's own file called route.js, located in the scripts folder.
Don't forget to include the newly created file in your index.html at the very bottom, just before app.js:
To make things even cleaner, let's also structure our code a bit better. Inside our new route.js we will define a single function called HERERoute hich will take the map and platform objects as parameters.
(By the way, you really should implement your own error handling in the onError callback. Simply printing the error to the console won't really cut it in the long run.)
Now we can call the function from within app.js:
A lot cleaner but the outcome hasn't really changed. Let's do something a bit more interesting, shall we?
Drawing the route
In order to make the route visible on the map, we need to implement the drawing mechanism within our onSuccess callback:
That's a lot of new code - let's step through some of the important parts:
First we have to check whether the request has actually returned a route at all. Assuming that's the case we will have to decide which routing option we want to use, as the API will return several routes. For simplicity's sake we'll use the first result.
With a route object at hand, we have to extract some data which we can pass onto the map's rendering mechanism. Remember how we have requested the response in display format? This decision will pay off now as we can simply grab the shape property for our route in order to draw it:
We still need do to a bit formatting nonetheless and we'll use one of our data types for that purpose. H.geo.Strip is an ordered, flat list of latitude and longitude pairs - perfect for us!
Finally we get to draw our route! For this purpose we'll utilize the map's polyline class H.map.Polyline. We even have control over the appearance of our route on the map - let's draw a nice, blue line between the start and end point:
One last thing: In order to ensure that the route is always fully visible let's update the map by matching the map bounds to the bounds of our route:
The time has come! Go and refresh your browser window and you should see a big, fat, blue route rendered onto your map. Well done!
Putting the pieces together
In the previous post of this series we've requested the user's geolocation and then placed a marker accordingly on the map. Let's use our current location as the origin for our route and place a marker.
As the waypoints have to be defined as a string in a predefined format, let's start by writing a small helper which converts a location into a waypoint:
Next we request the user's current location using navigator.watchPosition. For now we'll set a flag called isRouteRendered to ensure that the route is only rendered the first time - we will implement a more sophisticated solution later.
Refresh your browser once more and there you have it - a route calculated from your current position to HERE's HQ in Berlin. Nicely done!
Today we have learned to request routing information for two locations and render the result onto our map. In the next post we are going to start with some more refactoring and then take a closer look at some more advanced routing features of the HERE APIs. Stay tuned!