Google Maps and jQuery – calculating distance between two points
It has been a long time since I wrote my last example, but I've been really busy. Lately I got a request to write an example about calculating the distance between two points using KML file. What I will show you in this example is how to provide an user two drop down fields, which will be build according to provided KML file. Choosing each field will show a marker on the map. Changing the drop down field will cause removal of an according marker and placement of it in a new location. Also the markers will have two different colors, so an user can differentiate between starting and ending point. As the last functionality we will add a button. After an user clicks on the button, our function will calculate the rout and display the distance in kilometers. Let's start with a simple class which we will use to display drop down field and retrieve the coordination of requested place.
To see, how our final solution will look like, go here
1. Geo Class - Geo.class.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | class Geo { private $xml; protected function _init() { $this->xml = simplexml_load_file('geo.xml', 'SimpleXMLElement'); } public function getDropDown($id, $option = array()) { $this->_init(); $select = '<select name="' . $id . '" id="' . $id . '">'; if ($option['include_custom'] != '') $select.= '<option value="" selected="selected">' . $option['include_custom'] . '</option>'; foreach ($this->xml->children() as $child) { $select.= '<option value="' . $child->name . '">' . $child->name . '</option>'; } $select.= '</select>'; return $select; } public function getLocation($identifier) { $this->_init(); $coordinates = array(); foreach ($this->xml->children() as $child) if ($child->name == $identifier) { $temp = explode(',', $child->Point->coordinates); $coordinates = array( 'lat' => $temp[0], 'lng' => $temp[1] ); } return $coordinates; } } |
It wasn't really necessary to put this functions into a class, but it is just a habit
We define a protected function _init(), which we call every time we want to use our KML file to retrieve information out of it. The function simplexml_load_file initializes an SimpleXMLElement object for us, which we can use later. The function getDropDown with the first mandatory argument and the second optional will be responsible for displaying the drop down field for us. I think I don't need to explain it in detail. The last function getLocation will retrieve the latitude and longitude from KML file. So let's move to index.php file, which will be the core of this example.
2. Core file - index.php
1 2 | include('Geo.class.php'); $geo = new Geo(); |
Before we send any headers we include our Geo.class.php file and initialize our Geo class. After that goes the usual tag tags and the google maps and jQuery scripts. In the
section of our document goes the actual jQuery part.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | $(document).ready(function() { var mapContainer = $('#map')[0]; var markerStart; var markerEnd; if(GBrowserIsCompatible()) { if(mapContainer) { var map = new GMap2(mapContainer); map.addControl(new GLargeMapControl); map.setCenter(new GLatLng(52.519015140666,13.419671058654785), 14); $('#start').change(function() { var location = $(this).val(); if (location == '') return; $.getJSON('helper.php', { location: location }, function(data) { if (markerStart) map.removeOverlay(markerStart); pointA = new GLatLng(data.lat, data.lng); markerStart = new GMarker(pointA); map.addOverlay(markerStart); }); }); $('#end').change(function() { var location = $(this).val(); if (location == '') return; $.getJSON('helper.php', { location: location }, function(data) { if (markerEnd) map.removeOverlay(markerEnd); var blueIcon = new GIcon(G_DEFAULT_ICON); blueIcon.image = "http://gmaps-samples.googlecode.com/svn/trunk/markers/blue/blank.png"; var markerEndOptions = { icon: blueIcon }; pointB = new GLatLng(data.lat, data.lng); markerEnd = new GMarker(pointB, markerEndOptions); map.addOverlay(markerEnd); }); }); $('#submit').click(function() { if (window.pointA === undefined || window.pointB === undefined) { alert("You need to choose start and end"); return; } var directions = new GDirections(map); route = Array(pointA, pointB); GEvent.addListener(directions, 'load', function() { var dist = directions.getDistance().html; $('#distance').html(dist); }); directions.loadFromWaypoints(route); }); } } }); |
Maybe it is long but pretty straight forward. As you can read in my other examples, we first initialize jQuery, so it starts after our document is loaded. After that we define our map container and our markers. After we check if our browser is compatible and our map container exists, we initialize the map with couple options (large controls, zoom level = 14 and the center of the map).
We add two event listeners, which are triggered on onchange event of our drop downs (with id start and end respectively, the html code will follow). If you use the $option parameter in getDropDown function for displaying custom blank option, we check if the user chose this option and return false if he did. If he chose a valid option, we use an AJAX request and retrieve the geolocation from our helper file.
After our call returns some data, we check, if we have already any markers saved in our map and if we do, we first remove them and then place a new marker according to the option chosen in the drop down.
We repeat the same for the drop down with id 'end'. Actually we could have put this two events into a separate function, but to make this example clear I purposely didn't do that.
The last event listener is triggered, when a user clicks on a 'calculate route' button. First we check, if both points were placed by the user, and if not we display an alert, that he or she has to provide valid starting and ending point. This check might not work in IE, therefore you might need to do some changes, so it also works in IE.
We initialize GDirections Class and define our route with starting and ending point. I also use the getDistance method to display the amount of kilometers between this two points. As the last thing we need to do is to display the directions on the map and voila, we are done
What we still need it the rest of index.php file and our helper, and KML file.
1 2 3 4 5 6 7 | <div id="navigation">
Start <?php echo $geo->getDropDown('start', array('include_custom' => 'please choose...')); ?>
Stop <?php echo $geo->getDropDown('end', array('include_custom' => 'please choose...')); ?>
<input type="button" name="submit" id="submit" value="calculate route" />
</div>
<div id="distance"></div>
<div id="map" style="width: 1000px; height: 600px;"></div> |
Pretty straight forward. We display our navigation with an empty option 'please choose...', the 'calculate route' button and containers for distance and map.
3. Our helper - helper.php
1 2 3 | include('Geo.class.php'); $geo = new Geo(); echo json_encode($geo->getLocation($_GET['location'])); |
Pretty simple, isn't it
Just initialize the class and call the method to retrieve location with the location argument used in the _GET request.
4. KML file - geo.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://earth.google.com/kml/2.2"> <Placemark> <name>Alexanderplatz</name> <description>Center of Berlin</description> <Point> <coordinates>52.52238370531909,13.409671783447266</coordinates> </Point> </Placemark> <Placemark> <name>Frankfurter Tor</name> <description>A nice place to live</description> <Point> <coordinates>52.51595970749194,13.4527587890625</coordinates> </Point> </Placemark> <Placemark> <name>Warschauerstr.</name> <description>Place to go and spend some time with friends</description> <Point> <coordinates>52.508568336719854,13.451085090637207</coordinates> </Point> </Placemark> <Placemark> <name>Revelerstr.</name> <description>Cassiopeia Club</description> <Point> <coordinates>52.50721006978328,13.457050323486328</coordinates> </Point> </Placemark> <Placemark> <name>Frankfurter Allee</name> <description>Shopping Center</description> <Point> <coordinates>52.513818166144006,13.474087715148926</coordinates> </Point> </Placemark> </kml> |
It is a file I prepared by myself. As far as I know, you can create them using the Google Earth application. Probably they can be way more complex than this one. But I guess it will be a nice subject for next example
Good luck with this one and as usually, in case of any question, you know how to find me. Cheers!
November 14th, 2008 - 02:55
Thank you for that example on point data. Is it possible to create a drop down menu to search through a line kml file that’s already created in google maps?
November 14th, 2008 - 10:00
To be honest I have no idea. You have to compare the content of the KML file generated by google maps with the content of my KML file.
I toke it’s content from google developer center, so I assume it has to be similar. The only difference might be the complexity (extra information about a Placemark).
The best way would be for you to post a part of this file in here and I can take a look at it.