Google Maps in Five Minutes

Mar 5, 11:00 pm

Article Author: Michael Coles
.NET 3.5 Books

Introduction


In this article I will discuss how to create custom maps with the Google Maps API (version 1.0), step-by-step. Everything from creating a basic Google Map to using Asynchronous JavaScript and XML (AJAX) to plot points on your map will be covered, with live examples.


While this article isn t about AJAX tools and techniques specifically, the Google Maps API relies heavily on AJAX in the backend, and developers can utilize AJAX tools and techniques to supply Google Maps projects with the required data. Because it is so important to Google Maps, I ve provided some links to AJAX-related materials in the Related-Links section.


I will start by presenting a sample that works through a basic Google Map in detail to lay the foundation for the other samples. The second sample will show how to place markers and icons. Finally the last sample will use everything you have learned as well as adding some animation to provide an interactive example of using Google Maps.


System Requirements


To run the sample code for this article you should have:


A hosted website/domain name


A Google Maps API license key (see the Signing Up section for details)


A Google Maps-compatible browser (see the Browser Compatibility section for details)


An HTML or text editor


Signing Up


The very first step to using the Google Maps API is to acquire a hosted domain name. If you don t already have a domain name and web host, you can sign up for free domain/web hosting at many sites around the Web. I set up a sample domain at http://maps.geocodenet.com/ for the samples used in this article. If you do not own your own domain, you can purchase one or set up a domain or hosted directory at a free web host, such as http://www.geocities.com.


Once you have a domain name, or hosted site, sign up for a license key at http://www.google.com/apis/maps/signup.html. Google will email you a license key tied to your domain/hosted site. Only requests made from pages on your domain will be able to use your license key. To make this perfectly clear, you need to register with either your own hosted domain, such as http://maps.geocode.net or a subdirectory on a free Web hosting service, such as http://www.geocities.com/google_mapping.


According to the Google API Terms and Conditions, you can use your license key for "about 50,000 page views per day."


Installing the Sample Code


All of the code in the samples provided is JavaScript and HTML. The Google Maps API code is primarily in JavaScript which can be included inline in your HTML web pages. Follow the steps below in order to install the sample application on your website:


  1. Extract the downloaded sample to your local drive

  2. Replace [YOUR API KEY] in the <SCRIPT SRC= "…"> tag with your Google Maps API key

  3. Save the edited files

  4. Copy (FTP) the complete application directories up to your website

Sample 1: Getting Started


After you sign up for your Google Maps license, Google generates custom code for a simple Google Map automatically. The basic auto-generated sample map can be seen in Figure 1 (view this live demo at http://maps.geocodenet.com/basic):



Figure 1. The basic auto-generated Google Map


Here s the code that generates this basic map (line numbers are included for reference only):



 1: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 2:    <html xmlns="http://www.w3.org/1999/xhtml">
 3:       <head>
 4:          <title>Basic Google Map</title>
 5:          <script src="http://maps.google.com/maps?file=api&v=1&key=[YOUR 
                API KEY]" type="text/javascript"></script>
 6:       </head>
 7:       <body>
 8:          <div id="map" style="width: 500px; height: 400px"></div>
 9:             <script type="text/javascript">
10: //<![CDATA[
11: var map = new GMap(document.getElementById("map"));
12: map.addControl(new GSmallMapControl());
13: map.centerAndZoom(new GPoint(-122.1419, 37.4419), 4);
14: //]]>
15: </script>
16: </body>
17: </html>


Here s a run-through of the code line by line to get an idea of how it works:



 1: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">


Line 1 defines the XML DTD for this page. It is recommended that you use the XHTML 1.0 Strict DTD, as specified automatically for you here. Keep in mind that some free web hosts might add banners and content to your page that specify a different DTD, which might cause compatibility problems.



 2:    <html xmlns="http://www.w3.org/1999/xhtml">


Line 2 specifies the standard <html> opening tag and XML namespace for XHTML.



 3:       <head>
 4:          <title>Basic Google Map</title>
 5:          <script src="http://maps.google.com/maps?file=api&v=1&key=[YOUR 
API KEY]" type="text/javascript"></script> 6: </head>


Notice the <script> tag on line 5. This imports the Google Maps API JavaScript library. Your previously acquired API key needs to be placed on this line after the key= parameter.



 7:       <body>
 8:          <div id="map" style="width: 500px; height: 400px"></div>


The <div> on line 8 specifies the location where the map will be rendered within the body of the page by the GMap object. By default it s named map, but you can name it pretty much anything you wish. The style applied to the <div> uses CSS to define the width and height of the map in pixels.



 9:             <script type="text/javascript">
10: //<![CDATA[
11: var map = new GMap(document.getElementById("map"));
12: map.addControl(new GSmallMapControl());
13: map.centerAndZoom(new GPoint(-122.1419, 37.4419), 4);
14: //]]>
15: </script>


Lines 11 – 13 actually create your map like this:


Line 11 creates a GMap object, which is the actual Google map. The document.getElementById("map") function passes in the <div> element to the GMap constructor.


The GSmallMapControl in Line 12 is added to the map. This control lets your user zoom in and out of the map. Alternatively you can add a GLargeMapControl to the map, which is a larger version of the map zoom control.


Line 13 performs a centerAndZoom() on the map, placing it directly over Palo Alto, California. You can change the start position by modifying the latitude/longitude coordinates in the GPoint constructor of this line.


Line 13 also specifies that we start at zoom level 4. Valid zoom levels range from 0 (high detail) to 17 (world-wide wrap-around).


Initial Settings


There are several initial settings options that can be tweaked in your maps. As mentioned above, you can change the start location, zoom level, height and width of the map. In addition you can select one of three available initial map types by using the setMapType() method of the GMap object.



map.setMapType(G_MAP_TYPE);         // sets an initial standard map
map.setMapType(G_SATELLITE_TYPE); // sets an initial satellite map
map.setMapType(G_HYBRID_TYPE); // sets an initial hybrid map type


You can also add a GMapTypeControl to your GMap which will allow users to switch between these three map types:



map.addControl(new GMapTypeControl());


Browser Compatibility


One of the first steps to creating an advanced map is to check for browser compatibility. Google Maps provides a function called GBrowserIsCompatible() that performs a browser compatibility check. According to the API documentation, Google Maps API is compatible with Firefox/Mozilla, IE 5.5+, Safari 1.2+, Opera ("sort of"). We will create a function called onLoad() in the <head> section of the web page that will be executed when the page is loaded. It will perform a check, and display the Google Map if the browser is compatible – or a "Sorry" message graphic if not.


Note: In testing I encountered issues displaying Google Maps in the current IE 7 Beta.



 1: function onLoad() {       
 2:  //<![CDATA[
 3:  if (GBrowserIsCompatible()) {
 4:    var map = new GMap(document.getElementById("map"));
 5:    map.addControl(new GSmallMapControl());
 6:    map.centerAndZoom(new GPoint(-122.1419, 37.4419), 4);
 7:  } else {
 8:    document.getElementById("map").innerHTML = "<img src=‘Sorry.gif’ />";
 9:  }
10: //]]>
11: }


This function calls the GBrowserIsCompatible() function on line 3. If the function returns true, the GMap is created in lines 4 – 6. Otherwise we set the innerHTML of our <div> to the image of a "Sorry" message graphic specified on line 8. We add this function to the onload() event of the <body> tag to ensure it executes at page load.


Also, whichever browser you use must have JavaScript enabled in order to use the GoogleMaps API. To catch browsers that don t have JavaScript enabled, we add the <noscript> tag to the <head> of the page:



1: <noscript>
2: <img src="Sorry2.gif">
3: </noscript>


If JavaScript is disabled on the client browser, a "Sorry" message is displayed advising the user to turn on JavaScript to continue.


Sample 2: Adding Icons and Markers


Icons and markers allow you to place graphic representations of points on your map. Icons can be pushpins, flags, houses, or any other graphic you feel adequately represents the types of points you are trying to map. The default Google Maps icon is based on the mm_20_red icon available at http://labs.google.com/ridefinder/images/mm_20_red.png. This icon is a simple (see Figure 2), but funky, 12 pixel x 20 pixel red pushpin icon:



Figure 2. Default Google Map Pushpin Icon (blown-up)


You add these icons to your map by first creating a new GPoint item, creating a new GMarker for that point, and finally by adding the marker to the map overlay. In our sample we will add a single point to the map at Madison Square Garden in New York City. We will also set the initial zoom to 0 (the closest zoom level), and the initial map type to hybrid mode (which displays a hybrid satellite/street map.) Figure 3 demonstrates the result we re aiming for (the live sample of this map can be viewed at http://maps.geocodenet.com/icons):



Figure 3. Adding a marker at Madison Square Garden


This map defaults to hybrid mode, zoomed in to the maximum at Madison Square Garden in New York City. A single red pushpin on the Garden displays a pop-up Info Window when you click on it. You ll look at the code used to create this map and how it differs from the first map.


To begin, I add a CSS styles to the <head> of the web page. This style, called bubble, defines how the pop-up info window will look.



 1: <style type="text/css">
 2:    .bubble {
 3:       width:          350px; 
 4:       max-width:      350px;
 5:       text-align:     left;
 6:       font-family:    verdana,helvetica,arial,sans-serif;
 7:       font-size:      11px;
 8:       font-weight:    normal;
 9:    }
10: .bubble h1 {
11: font-size: 11px;
12: margin-bottom: 4px;
13: font-weight: bolder;
14: }
15: .bubble h2 {
16: font-size: 11px;
17: margin-bottom: 4px;
18: font-weight: bolder;
19: font-style: italic;
20: }
21: </style>


The basic bubble style defines a 350px wide info window, in a normal font. The <h1> and <h2> tags of the bubble style define bold/italic variations for the header and footer.


Next I modify the onLoad() function to look like the following:



 1:  function onLoad() {       
 2:    //<![CDATA[
 3:    if (GBrowserIsCompatible()) {
 4:      var point = new GPoint(-73.99348855, 40.75031877);
 5:      var map = new GMap(document.getElementById("map"));
 6:      map.addControl(new GLargeMapControl());
 7:      map.addControl(new GMapTypeControl());
 8:      map.setMapType(G_HYBRID_TYPE);
 9:      map.centerAndZoom(point, 0);
10: var marker = new GMarker(point);
11: var info = ‘<div class="bubble"><h1>Madison ‘ +
12: ‘Square Garden</h1>&quot;Madison Square Garden, often abbreviated ‘ +
13: ‘as MSG, has been the name of four arenas in New York City, United ‘ +
14: ‘States. The first two were located at Madison Square, thus the ‘ +
15: ‘name. Subsequently a new 20,000-seat Garden was built at 50th ‘ +
16: ‘Street and 8th Avenue, and the current Garden is at 7th Avenue ‘ +
17: ‘between 31st and 33rd Streets, situated on top of Pennsylvania ‘ +
18: ‘Station.&quot;<h2>-Wikipedia</h2></div>’;
19: GEvent.addListener(marker, "click", function() {
20: marker.openInfoWindowHtml(info);
21: });
22: map.addOverlay(marker);
23: } else {
24: document.getElementById("map").innerHTML = "<img src=‘Sorry.gif’ />";
25: }
26: //]]>
27: }
28: </script>


In line 3, I perform the standard Google Maps browser compatibility check. If an incompatible browser is found, the script drops down to lines 23 – 25 to display the "Sorry" graphic message. If the browser is compatible, lines 4 – 22 are executed:


Line 4 creates a GPoint with the coordinates of Madison Square Garden.


Lines 5 – 9 create the map, add a GLargeMapControl, a GMapTypeControl, sets the initial map type to hybrid mode and finally centers and zooms the map on the point. Notice that I center the map before adding the GMarker items to it, this avoids possible errors in Internet Explorer when you add the GMarkers first.


In line 10, I create a new GMarker based on the GPoint created earlier. I then use the map s addOverlay() method to add the GMarker to the map. Since I don t specify an icon, the default Google pushpin icon is used.


Lines 11 – 18 generate the HTML-formatted info window information.


Line 19 – 21 adds an info window to the marker created above. In this line, a "click" event listener is added to the marker. The click event is tied to a function that performs the openInfoWindowHtml() function on the marker.


In line 22 the marker is added to the map, via the map s addOverlay() method.


Sample 3: See George Run


In this final map, I ll combine some advanced topics with the items I ve covered in the previous samples. This map will follow a dollar bill (refereed to as George due to a picture of George Washington being on the US dollar bill) on its journey across the United States, as recorded on the http://www.wheresgeorge.com website. I ll use everything we ve already covered in the previous samples and add some new tricks, including animation, custom icons, polylines and automatic re-centering. The sample map application will look like Figure 4(the live sample can be viewed at http://maps.geocodenet.com/george):



Figure 4. Sample Google Map with Animation


This map will interact with other screen elements as part of a larger application that will do the following:


  • Read and plot the points in an XML file for George s trip

  • Calculate distances between points on the trip

  • Draw polylines between points on the trip

  • Animate the dollar bill icon so that it moves along the path between points on the trip

  • Display tracking information (current location and distance) on the web page as George moves

  • Keep George on the screen at all times

That s a lot to do, but still not too difficult with the Google Map API.


Everything So Far…


In this sample, we read in and parse an XML data file to get the point plotting information. The file is called trip.xml and it contains all of the data required for George s trip across the country. It s in the following format:



<?xml version="1.0" encoding="utf-8" ?>
<trip> <loc number="1" long="-86.18" lat="36.77" city="Scottsville" state="KY" /> <loc number="2" long="-86.62" lat="35.62" city="Chapel Hill" state="TN" /> <loc number="3" long="-86.57" lat="35.62" city="Unionville" state="TN" />
</trip>


Each <loc> tag represents a separate location/point along George s route. Also, as in the States sample, I define styles to display the info window, and add browser compatibility/JavaScript checks.


Using Custom Icons


For this sample map, I am using two custom icons: a flag icon and a dollar bill icon, both with shadows. Note that if you create a custom icon, and would like a shadow on it, you have to create the shadow yourself. The shadow and the icon are actually two separate images. I then created custom GIcon objects in the onLoad() function as shown below:



 1: var pinicon = new GIcon();
 2: pinicon.image = "flag.png";
 3: pinicon.iconSize = new GSize(24, 24);
 4: pinicon.shadow = "flag_shadow.png";
 5: pinicon.shadowSize = new GSize(37, 28);
 6: pinicon.iconAnchor = new GPoint(14, 1);
 7: pinicon.infoWindowAnchor = new GPoint (0, 0);
 8: pinicon.infoShadowAnchor = new GPoint (3, 0);
 9: var georgeicon = new GIcon();
10: georgeicon.image = "george.png";
11: georgeicon.iconSize = new GSize(94, 40);
12: georgeicon.shadow = "george_shadow.png";
13: georgeicon.shadowSize = new GSize(127, 47);
14: georgeicon.iconAnchor = new GPoint(47, 0);
15: georgeicon.infoWindowAnchor = new GPoint (12, 0);
16: georgeicon.infoShadowAnchor = new GPoint (8, 0);


The pinicon variable represents a custom push-pin (in this case the flag graphic). The georgeicon represents the dollar bill graphic. I now have two custom icons that I can assign to GMarker objects on creation. In this sample map, the code to do this falls on two separate lines:



marker[i] = new GMarker(point[i], pinicon);
george = new GMarker(georgepoint, georgeicon);


The first line creates a new GMarker at a point previously defined (in this case, point[i] represents the route points specified in the XML data file). The second line places the dollar bill icon at the georgepoint, which starts out at the first point on the trip.


The remaining code to loop through the points specified in the XML file and plot them on the map is very similar to the code in the States sample.


Adding Polylines


Polylines are lines that can be rendered on the map between any two given points. Internet Explorer has some built-in the VML (Vector Markup Language) extensions that Google Maps API can take advantage of when rendering polylines. VML polylines can be rendered faster than bit-map graphic polylines. For other browsers that don t support VML, Google Maps API generates polylines as bitmap graphics and displays them over the map.


In order to take advantage of polylines in IE, I ve added some code to the beginning of the page. In particular, note that <html> tag has been changed, and a new style has been added. The <html> tag now looks like this:



<html xmlns="http://www.w3.org/1999/xhtml" 
  dxmlns:v="urn:schemas-microsoft-com:vml">


I ve added the xmlns:v namespace to the tag. The stylesheet which has been added is:



<style type="text/css">
  v:*{
      behavior:url(#default#VML);
  }
</style>


Once that setup is out of the way, you can draw polylines by creating GPolyline objects. Although you can pass an array of as many points as you d like to the GPolyline constructor, I ve chosen to create these polylines in a loop, one at a time.



for (var i = 1; i < point.length; i++) {
  var polyline = new GPolyline([point[i – 1], point[i]], ‘#ff0000’);
  map.addOverlay(polyline);
}


The point[i] array contains all of the plotted points, so this loop will add a separate red polyline between each pair of connected points on my map.


Calculating the Distance


Distance calculations are used for a couple of purposes in this application. I have included a basic great circle distance calculation in the code, which approximates the distance (in miles) between two points to two decimal places. This is the calculation I use:



function great_circle(p1, p2) {
  //<![CDATA[
  var lon1 = p1.x * rad;
  var lat1 = p1.y * rad;
  var lon2 = p2.x * rad;
  var lat2 = p2.y * rad;
  var theta  =  lon2  –  lon1; 
  var dist  =  Math.acos(Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) *
               Math.cos(lat2) * Math.cos(theta)); 
  if  (dist  <  0)  
  {  
    dist  +=  Math.PI;
  } 
  dist = dist * 6371.2; 
  var miles = Math.round(dist * 0.621 * 100.0) / 100.0;
  return miles;
  //]]>
}


I won t go into too much detail on how the calculation does what it does, but the following Wikipedia article describes great circle distance calculations in great detail: http://en.wikipedia.org/wiki/Great_circle_distance.


In this application, I use the great circle distance to calculate the number of moves George must take between two points, and I display the distance information to the user as George heads out for each new city.


Making George Move – Animation


The animation routine simply moves George around the screen, updating his position at specified intervals. This section is composed primarily of two functions I created. They are the move calculation (calc_moves()) function and the actual movement routine (MoveGeorge()).


The calc_moves() function calculates each step of George s journey between any two points. It s called as he starts out, and then again after each destination is reached.



function calc_moves(p1, p2) {
  //<![CDATA[
    next_step = false;
    position = p1;
    end = p2;
    max_moves = great_circle(position, end);
    move_count = 0;
    xdelta = (p2.x – p1.x) / max_moves;
    ydelta = (p2.y – p1.y) / max_moves;
  //]]>
}


In this function I calculate the maximum number of moves. Then I calculate the difference between longitude and latitude coordinates between the start and end positions. Finally, I divide these differences by the maximum number of moves to get delta values for each step of the trip from the start point to the end point.


The heart of the MoveGeorge() routine is in the following if statement:



if (move_count < max_moves) {
  george.point.x += xdelta;
  george.point.y += ydelta;
  george.redraw(true);
  move_count = move_count + 1;
  KeepGeorgeOnTheMap();
  setTimeout(‘MoveGeorge()’, 1);
}


This statement checks to see if George has reached the maximum number of moves yet. If not, it adds the xdelta and ydelta values to George s current location and re-draws George at the new location. It then calls KeepGeorgeOnTheMap() (see the next section for details), and recursively calls itself using JavaScript s setTimeout(). To slow down or speed up George, change the delay time in the setTimeout() function call.


Boundary Checking and Auto-Centering


The KeepGeorgeOnTheMap() function is another function I added to the application. It is designed to keep George visible at all times. It performs a simple boundary check and if George is out of bounds, the screen is re-centered:



function KeepGeorgeOnTheMap() {
  //<![CDATA[
  var bounds = map.getBoundsLatLng();    
  if ((george.point.x > bounds.maxX) || (george.point.x < bounds.minX) || 
      (george.point.y > bounds.maxY) || (george.point.y < bounds.minY))    
  {   
    map.recenterOrPanToLatLng(george.point);   
  }   
  //]]>
}


The Google Maps API getBoundsLatLng() function of the map returns the boundaries of the currently visible portion of the map. By checking George s current latitude and longitude against the visible map boundaries, I can readjust on the fly using the Google Maps API recenterOrPanToLatLng() function to keep George visible.


A Note About Geocoding


The sample maps provided use static, pre-geocoded data. Several websites offer dynamic web-based geocoding services, including http://www.geocoder.us (which was used for the samples in this article) and http://www.yahoo.com. Currently Google itself does not offer a free geocoding web-based service for use with Google Maps.


Coming Soon: Version 2.0


All of the samples and code provided here apply to version 1.0 of the Google Maps API. Although version 2.0 is currently being tested by thousands of users around the world, Google has not officially released it yet. There will be several differences in the way version 2.0 handles mapping, including new names for commonly used functions, a complete reversal of the zoom function (0 will be the highest level), and completely new ways to handle other tasks. Because version 2.0 has not been finalized, I decided to focus this article completely on version 1.0. Further information on the version 2.0 beta is available at http://www.mapki.com.


Conclusion


The Google Maps API is changing the way a lot of people think about mapping projects, and creating a whole new subset of interactive web applications. In this article I discussed how to create custom Google Maps using the Google Maps API. I talked about basic map creation, dynamic loading of content using XML and JavaScript, browser compatibility, Google Map controls, info windows, polylines, custom icons, animation and bounds checking. Sample code and live samples were provided as well.


Using the Google Maps API, you can quickly and easily add professional quality maps to your own websites and web-based applications. Many existing applications include real estate applications, real-time tracking tools, educational programs and even games can benefit from the use of the Google Maps API. The possibilities of incorporating real-time geographic representations into new or existing applications are almost limitless. A multitude of existing geographically-enabled applications already exist; and more are on the way.


Credits


I would like to thank the following people and/or websites deserve credit for information used in this article and/or in the sample applications:


Rich Gibson at http://www.geocoder.us for allowing me to use his geocoding services for Samples #2 and #3.


http://www.wikipedia.com supplied the state flag images used in Sample #3, and http://www.50states.com provided their fun facts about each state used in the same sample.


http://www.wheresgeorge.com/ for the George s tracking information (used in Sample #4).

Founders at Work

Commenting is closed for this article.