Skip to main content

Drawing paths on Google Maps, the Indiana Jones way

I was looking into the Google Maps API the other day and came across some APIs which are really cool. I came up with a use case to show path from the current location to a particular destination entered by the user. I was also trying to achieve that Indiana Jones like effect on the map i.e. to show an animation of the path being drawn on the map.


The idea here is to show the moving path until the destination is reached and also to pan the map accordingly.

Unable to display content. Adobe Flash is required.

As seen in the video, a marker is added to the map specifying my current location (Bangalore, India). The current location data is retrieved using the HTML5’s Geolocation API. Once the latitude and longitude information are available, a marker can be added to the map. You can now enter one of your favorite destinations in the text box provided and click the Submit button to see a path drawn from your current location to the destination. The path is drawn using the Google maps ‘Polyline’ API.

Getting the current location data using HTML5’s Geolocation API:

The Geolocation API allows users share their current location information with trusted sites. You can examine the property navigator.geolocation to see whether the browser supports the Geolocation API. Alternatively, Modernizr can be used to determine the same. All modern browsers support the Geolocation API; however users are required to provide permission to the websites. Once the user has provided the permission, the method getCurrentPosition can be invoked on the navigator.geolocation object:
 navigator.geolocation.getCurrentPosition(function(position){  
     var mapElement = document.getElementById('mapelement');  
     startLatitude = position.coords.latitude;  
     startLongitude = position.coords.longitude;  
     mapObj = new google.maps.Map(mapElement,  
     {  
         disableDefaultUI:true,  
         zoom: 3,  
         center: new google.maps.LatLng(startLatitude,startLongitude),  
         mapTypeId: google.maps.MapTypeId.TERRAIN  
     });  
     var markerPosition = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);  
     var startPosition = markerPosition;                                     
     var marker = new google.maps.Marker({position:markerPosition,map:mapObj,title:'You are here'});       
});  

Once the latitude and longitude information is available, they can be used to specify the center address and to add a marker on the map.


Drawing the path using the Polyline API:


A polyline is a linear overlay of connected line segments on the map. To draw a line on the map using the Polyline API, you have to pass the map object along with the coordinates specifying the end points as arguments. However, to get the Indiana Jones like effect, you must get as many points between the start and the end location. The latitude and longitude information of these points are then stored in an array and will later be used to achieve the desired effect.


For the purpose of this example, I’ve assumed 30 animation frames and have calculated the increment:

 function getPathData(destLatitude,destLongitude){  
    var xInc,yInc;  
    xInc = (destLatitude - startLatitude)/30;  
    yInc = (destLongitude - startLongitude)/30;  
    for(var i=0;i<30;i++){  
      path[i] = new google.maps.LatLng(startLatitude += xInc,startLongitude += yInc);       
    }  
 }  

The path array would then contain the latitude and longitude information for the points between the start and the end location. This information can then be used to draw the path and get the desired effect:

 function drawPath(){  
    var polyLine = new google.maps.Polyline({  
                       path: [startPosition,path[positionIndex]],  
                       strokeColor:'#FF0000',  
                       strokeOpacity:2,  
                       strokeWeight:8,  
                   });  
    polyLine.setMap(mapObj);  
    mapObj.panTo(path[positionIndex]);  
    positionIndex = positionIndex + 1;  
    if(positionIndex < 30){  
      setTimeout(drawPath,200);  
    }                            
 }  

As seen in the above code snippet, the Polyline API is invoked with the arguments path, strokeColor, strokeOpacity, and strokeWeight. Also, the map is panned to the current position while the path is being drawn on the map.


Can I use ColdFusion’s CFMAP tag to get this effect?


This was the initial idea and I did attempt to get this effect using the CFMAP tag. However, I found that the map object retrieved using the ColdFusion.map.getMapObject was not compatible with the Polyline API and hence decided to use the Google maps API to get that effect.

Comments

Popular posts from this blog

De-obfuscating javascript code in Chrome Developer Tools

I had blogged about JavaScript debugging with Chrome Developer Tools  some time back, wherein I have explained how these developer tools can help in debugging javascript code. Today Google Chrome 12 was released and my Chrome browser was updated to this version. As with every release, there have been some improvements made on performance, usability etc,. One feature that stood out for me is the ability to De-obfuscate the javascript code. What is Minification? Minification is the process of removing unnecessary characters such as white spaces, comments, new lines from the source code. These otherwise would be added to make the code more readable. Minifying the source code helps in reducing the file size and thereby reducing the time taken to download the file. This is the reason why most of the popular javascript libraries such as jQuery are minified. A minified jQuery file is of 31 KB in size where as an uncompressed one is about 229 KB. Unfortunately, debugging minified javascript f

Adding beforeRender and afterRender functions to a Backbone View

I was working on a Backbone application that updated the DOM when a response was received from the server. In a Backbone View, the initialize method would perform some operations and then call the render method to update the view. This worked fine, however there was scenario where in I wanted to perform some tasks before and after rendering the view. This can be considered as firing an event before and after the function had completed its execution. I found a very simple way to do this with Underscore's wrap method.

On GraphQL and building an application using React Apollo

When I visualize building an application, I would think of using React and Redux on the front-end which talks to a set of RESTful services built with Node and Hapi (or Express). However, over a period of time, I've realized that this approach does not scale well when you add new features to the front-end. For example, consider a page that displays user information along with courses that a user has enrolled in. At a later point, you decide to add a section that displays popular book titles that one can view and purchase. If every entity is considered as a microservice then to get data from three different microservices would require three http  requests to be sent by the front-end app. The performance of the app would degrade with the increase in the number of http requests. I read about GraphQL and knew that it is an ideal way of building an app and I need not look forward to anything else. The GraphQL layer can be viewed as a facade which sits on top of your RESTful services o