How to Build a Distance Finder with Google Maps API (Part-2)

Posted in Tutorials4 years ago • Written by 18 Comments

In the first part of this tutorial we’ve built a distance finder using google maps. To build our app we’ve used the newest google maps api version, v3. Our distance finder lets the user write two addresses, shows them on a map, shows the route between them and computes the route’s length. Today, we will make some improvements to our distance finder and learn some other features of google maps!

What are we going to add?

We’re going to add custom markers to our map and a new feature: draggable markers. The user will be able to drag the markers around the map and the route will be computed again. We will also let the user choose what type of route to show on the map (the available options are driving, walking and bicycling). Another thing we’ll add is saving the map type selected by the user. This way, the selection will be saved when the user presses the “show” button next time and the user won’t have to select the desired map type each time he refreshes the map.

You can check out the new version here and also download the source code.

Prerequisites

I recommend reading the first part of this tutorial if you haven’t already. In this one I’ll only describe the new features.

Apart from adding the new features, I’ve made a small change to the programs structure: I’ve made a separate function for showing the route between the two points (called drawRoutes()). I’ve done this because we’ll have to call this function each time one of the markers is dragged by the user.

Adding custom markers

The first thing we’ll add are custom markers. For this, we need a small image, I’ve used a silly one as an example. The code to set the image as the marker looks like this:

var rabbit = new google.maps.MarkerImage('distance-finder-custom-marker-image.png');
// create the markers for the two locations
var marker1 = new google.maps.Marker({
   map: map,
   position: location1,
   title: "First location",
   icon: rabbit,
   draggable: true
});
var marker2 = new google.maps.Marker({
   map: map,
   position: location2,
   title: "Second location",
   icon: rabbit,
   draggable: true
});

We’ve defined a new MarkerImage object and given it the location of the image for the marker. Also, we’ve changed the options a bit when creating the markers: we’ve added the icon parameter.

Making the markers draggable

As you can see from the previous piece of code, we’ve also set the “draggable” parameter to true, making our markers draggable. The user can now drag the markers anywhere on the map. But nothing happens when the markers are dragged! We’ll have to add the code to find the address of the new locations and show the new route. But first, we’ll have to add another action listener to the markers, to define the function to be called when the user stops dragging the marker.

Here’s what we have to add to our code:

// add action events for dragging the markers
google.maps.event.addListener(marker1, 'dragend', function() {
   location1 = marker1.getPosition();
   drawRoutes(location1, location2);
});
google.maps.event.addListener(marker2, 'dragend', function() {
   location2 = marker2.getPosition();
   drawRoutes(location1, location2);
});

We’ve added one listener for each marker. Both of them save the new location of the marker (we can get that using the getPosition() function from the google maps api – the function returns the marker’s coordinates) and call the drawRoutes() function giving it the new locations as parameters.

In the drawRoutes() function we’ll have to find the addresses of the new locations and show the new line between the points and compute a new route.

To find the addresses of the points we’ll use the reverse geocoding feature provided by google maps. Geocoding means finding the coordinates of a given address, and reverse geocoding means finding the address of the points when you know the coordinates.

Here’s  the code for this:

geocoder = new google.maps.Geocoder(); // creating a new geocode object
if (geocoder)
{
  geocoder.geocode({'latLng': location1}, function(results, status)
  {
    if (status == google.maps.GeocoderStatus.OK)
    {
      if (results[0])
      {
        address1 = results[0].formatted_address;
        document.getElementById("address1").value = address1;
      }
    }
    else
    {
      alert("Geocoder failed due to: " + status);
    }
  });
}

if (geocoder)
{
  geocoder.geocode({'latLng': location2}, function(results, status)
  {
    if (status == google.maps.GeocoderStatus.OK)
    {
      if (results[0])
      {
        address2 = results[0].formatted_address;
        document.getElementById("address2").value = address2;
        continueShowRoute(location1, location2);
      }
    }
    else
    {
      alert("Geocoder failed due to: " + status);
    }
  });
}

The code is very similar to the code we’ve used to geocode the addresses. We’ve created a new geocoder object and called the geocode function as before. This time, the parameter we sent to the function is the location of the points. We’ve saved the result from the google server and the address1 and address2 variables. The address has the following format: “275-291 Bedford Ave, Brooklyn, NY 11211, USA”. We’ve written this address in the text fields from the form, so the user will know the exact address of the plotted points. We’ve used the document.getElementById() to set the values of the text fields. When both addresses are found, we call the continueShowRoute() function which shows the routes.

We’ll first show the line that connects the points. The difference from the first tutorial is that we now have to delete the last drawn line. Like this:

// hide last line
if (line)
{
   line.setMap(null);
}

Then we’ll draw the new one, just like before.

We’ll then compute the distance on a straight line between the points and show it on the screen, as I’ve shown in the first tutorial. The code to compute the quickest route and show the results on the screen also remains unchanged. The only thing we need to do is update the text on the infowindows with the new address values.

// update text in infowindows
var text1 = '
<div>'+</div>
   '<h1 id="firstHeading">First location'+
   '<div id="bodyContent">'+
   'Coordinates: '+location1+'

'+
   'Address: '+address1+'

'+
   '</div>'+
   '</div>';
var text2 = '
<div>'+</div>
   '<h1 id="firstHeading">Second location</h1>'+
   '<div id="bodyContent">'+
   'Coordinates: '+location2+'

'+
   'Address: '+address2+'

'+
   '</div>'+
   '</div>';
infowindow1.setContent(text1);
infowindow2.setContent(text2);

We’ve created new variables for holding the new texts to be shown in the infoboxes and used the setContent() function to change the texts on them.

Choosing the travel mode

We’ll also add the option to change the driving mode for the route shown on the map. The available travel modes are: driving, walking and bicycling (this option is only available for routes in the US).

We’ll first have to add a drop down box for the user to select the desired travel mode. We’ll add a new row to our previously created table:

<tr>
  <td>Route type:
    <select id="<span class="></select>
      <option value="driving">driving</option>
      <option value="walking">walking</option>
      <option value="bicycling">bicycling (only in US)</option>
    </select>
  </td>
</tr>

Now, let’s see what we have to do to show the selected travel mode correctly. We’ll have to change the options for the request we send to the directions service from google.

var travelmode = document.getElementById("travelMode").value;
// get the selected travel mode
if (travelmode == "driving")
   travel = google.maps.DirectionsTravelMode.DRIVING;
else if (travelmode == "walking")
   travel = google.maps.DirectionsTravelMode.WALKING;
else if (travelmode == "bicycling")
   travel = google.maps.DirectionsTravelMode.BICYCLING;
// find and show route between the points
var request = {
   origin:location1,
   destination:location2,
   travelMode: travel
};

We’ve first saved the selected option from the drop down box in the travelmode variable. We’ve checked the value of this variable and set the travel variable that holds the google.map.travelmode. When setting the options for the request, we’ve used this variable to set the travel mode.

Saving the selected map setting

The map types the user can choose from are: roadmap, hybrid, satellite and terrain.

We’re going to use a hidden field in the form for holding the selected map

<input id="<span class=" />maptype" type="hidden" value="roadmap"/>

When creating the new map object, we’ll first check the value of this field and set the map type accordingly.

// get the map type value from the hidden field
var maptype = document.getElementById("maptype").value;
var typeId;
if (maptype == "roadmap")
   typeId = google.maps.MapTypeId.ROADMAP;
else if (maptype == "hybrid")
   typeId = google.maps.MapTypeId.HYBRID;
else if (maptype == "satellite")
   typeId = google.maps.MapTypeId.SATELLITE;
else if (maptype == "terrain")
   typeId = google.maps.MapTypeId.TERRAIN;

// set map options
var mapOptions =
{
   zoom: 1,
   center: latlng,
   mapTypeId: typeId
};

The last thing we need to do is update the hidden field value when the user changes the map type. For this, we need to add a listener that will be triggered when the user changes the map type. The listener will update the value of the hidden field.

// event listener to update the map type
google.maps.event.addListener(map, 'maptypeid_changed', function() {
   maptype = map.getMapTypeId();
   document.getElementById('maptype').value = maptype;
});

We’ve used the getMapTypeId() function to get the new map type and the document.getElementById() function to set the value for the hidden field.

And that’s it! We’ve finished improving our distance finder!

7 Written ArticlesWebsite

Irina is a software developer from Bucharest, Romania. She enjoys working on various programming projects. She likes spending her spare time reading, hiking, travelling, skating or playing tennis. She also blogs a bit. You can find her online in her home on the internet and on twitter.

18 Comments Best Comments First
  • Valentine Belonwu

    Friday, July 2nd, 2010 15:41

    1

    Nice article and well explained..I will be checking back on you. This is my 2nd time of visiting your blog.

    Keep up the great work.

    0
    • Irina

      Saturday, July 3rd, 2010 12:27

      4

      I’m glad you enjoyed it!

      0
  • Mike

    Saturday, July 3rd, 2010 22:00

    8

    Nice tutorial for me :) It’s chance to learn how to interact with Google Maps API and do some stuff. Thanks!

    0
  • Kimmo

    Saturday, July 3rd, 2010 09:43

    6

    I guess it would be nicer if you used arrays instead of if – else blocks. You could then just use selectEmt.selectedIndex to point directly to array items. Adding and removing map types and travel modes would be pretty trivial this way.

    Other than that, thumbs up!

    0
    • Irina

      Saturday, July 3rd, 2010 12:27

      5

      Thanks for the tip! Good idea :)

      0
  • Bojan

    Friday, July 2nd, 2010 13:35

    2

    Very nice! Can you go one step further? :)
    What I have in my mind is that make an “autocomplete” with input fields for geolocations (something like on Google Maps), what do you say? :)

    0
    • Irina

      Saturday, July 3rd, 2010 12:23

      7

      That sounds like a good idea. I might try it!

      0
  • Jon

    Friday, July 23rd, 2010 05:27

    9

    How do I preserve a map ? Just like a picture?

    0
  • TUM

    Sunday, August 1st, 2010 10:11

    10

    It seems like the real solution to me. I have not tried your script yet. It looks so helpful to me while i’m developing a map application for the college project and it dues in 3 days. Do you have the full working page to try on? THANKS

    0
    • Saad Bassi

      Sunday, August 1st, 2010 11:27

      11

      You can see the demo in start of article

      0
  • Gopi A

    Sunday, July 17th, 2011 17:10

    16

    Hey, great tutorials! There’s an error in part 2′s demo however..

    Please try inputting the following:
    1. Address 1: Mahatma Society, Kothrud, Pune, India
    2. Address 2: Sus Road, Pune, India

    In the first part, the mapping is perfect…but the 2nd one…the address changes completely and so do the points!

    0
  • vijay lathiya

    Monday, April 9th, 2012 02:19

    17

    thanks for excellent wonderful article,
    i tried for implementation in this script as user able to change their route way points instead of google default
    way on route between origin and destination point and distance also change according to way point change on route by user.
    but im not success to achieve my goal,
    can you help me to do it?
    thanks

    0
    • vijay lathiya

      Wednesday, April 11th, 2012 08:19

      18

      finally i done it.
      once again thanks for sharing useful script.

      0
  • Krish

    Thursday, September 23rd, 2010 12:32

    14

    Irina, Nice work on the article and glad that you wanted to share with all. I have a question. Is it first of all possible to plot more than one route ? meaning, one source-multiple destinations plotting alongwith the distance information for all destinations from the source listed one-by-one.. If it is possible, how to do that ?

    Thanks. You are doing great job and don’t forget to keep it going.

    0
    • Irina

      Monday, September 27th, 2010 14:23

      15

      Yes, of course you can do that. Just multiply the code for one route to show more :)

      0
  • ian garforth

    Monday, August 23rd, 2010 19:50

    12

    Great stuff. Thanks for this. How can I use the value of the journey duration – for example, to produce an alert box that only evaluates journeys less than a certain value?

    You can see my woeful attempt here, but it’s failed spectacularly. Can you help?

    Ian

    0
    • Irina Borozan

      Monday, September 13th, 2010 11:48

      13

      I’ve looked at your code. You just have to compare this result: response.routes[0].legs[0].duration.text with your maxtime value. And use the alert() function to show an alert box. I hope this helps ;)

      0
  • Irina

    Saturday, July 3rd, 2010 12:22

    3

    Thanks! I’m glad you liked it!

    0
  • vijay lathiya

    Monday, April 9th, 2012 02:19

    17

    thanks for excellent wonderful article,
    i tried for implementation in this script as user able to change their route way points instead of google default
    way on route between origin and destination point and distance also change according to way point change on route by user.
    but im not success to achieve my goal,
    can you help me to do it?
    thanks

    0
    • vijay lathiya

      Wednesday, April 11th, 2012 08:19

      18

      finally i done it.
      once again thanks for sharing useful script.

      0
  • Gopi A

    Sunday, July 17th, 2011 17:10

    16

    Hey, great tutorials! There’s an error in part 2′s demo however..

    Please try inputting the following:
    1. Address 1: Mahatma Society, Kothrud, Pune, India
    2. Address 2: Sus Road, Pune, India

    In the first part, the mapping is perfect…but the 2nd one…the address changes completely and so do the points!

    0
  • Krish

    Thursday, September 23rd, 2010 12:32

    14

    Irina, Nice work on the article and glad that you wanted to share with all. I have a question. Is it first of all possible to plot more than one route ? meaning, one source-multiple destinations plotting alongwith the distance information for all destinations from the source listed one-by-one.. If it is possible, how to do that ?

    Thanks. You are doing great job and don’t forget to keep it going.

    0
    • Irina

      Monday, September 27th, 2010 14:23

      15

      Yes, of course you can do that. Just multiply the code for one route to show more :)

      0
  • ian garforth

    Monday, August 23rd, 2010 19:50

    12

    Great stuff. Thanks for this. How can I use the value of the journey duration – for example, to produce an alert box that only evaluates journeys less than a certain value?

    You can see my woeful attempt here, but it’s failed spectacularly. Can you help?

    Ian

    0
    • Irina Borozan

      Monday, September 13th, 2010 11:48

      13

      I’ve looked at your code. You just have to compare this result: response.routes[0].legs[0].duration.text with your maxtime value. And use the alert() function to show an alert box. I hope this helps ;)

      0
  • TUM

    Sunday, August 1st, 2010 10:11

    10

    It seems like the real solution to me. I have not tried your script yet. It looks so helpful to me while i’m developing a map application for the college project and it dues in 3 days. Do you have the full working page to try on? THANKS

    0
    • Saad Bassi

      Sunday, August 1st, 2010 11:27

      11

      You can see the demo in start of article

      0
  • Jon

    Friday, July 23rd, 2010 05:27

    9

    How do I preserve a map ? Just like a picture?

    0
  • Mike

    Saturday, July 3rd, 2010 22:00

    8

    Nice tutorial for me :) It’s chance to learn how to interact with Google Maps API and do some stuff. Thanks!

    0
  • Kimmo

    Saturday, July 3rd, 2010 09:43

    6

    I guess it would be nicer if you used arrays instead of if – else blocks. You could then just use selectEmt.selectedIndex to point directly to array items. Adding and removing map types and travel modes would be pretty trivial this way.

    Other than that, thumbs up!

    0
    • Irina

      Saturday, July 3rd, 2010 12:27

      5

      Thanks for the tip! Good idea :)

      0
  • Bojan

    Friday, July 2nd, 2010 13:35

    2

    Very nice! Can you go one step further? :)
    What I have in my mind is that make an “autocomplete” with input fields for geolocations (something like on Google Maps), what do you say? :)

    0
    • Irina

      Saturday, July 3rd, 2010 12:23

      7

      That sounds like a good idea. I might try it!

      0
  • Valentine Belonwu

    Friday, July 2nd, 2010 15:41

    1

    Nice article and well explained..I will be checking back on you. This is my 2nd time of visiting your blog.

    Keep up the great work.

    0
    • Irina

      Saturday, July 3rd, 2010 12:27

      4

      I’m glad you enjoyed it!

      0
  • Irina

    Saturday, July 3rd, 2010 12:22

    3

    Thanks! I’m glad you liked it!

    0

Comments are closed.

54.197.189.108 - unknown - unknown - US