GMaps: Using multiple API versions

Four months ago Google released a new version of their Maps API, version 3, which promised substantial speed improvements and support for mobile browser among other benefits. It's a complete rewrite and its interface is significantly different from the current API. And yet it may still be possible to write modules that work with both APIs as this post shows.

As it turned out, the differences between the APIs are not as significant as I originally expected; although I only used a small chunk of the API, the result still provides a fully functional and potentially useful example.

I am going to use dynamic loading of the API to allow easy switching between the two versions. I am also going to set up a namespace to encapsulate the code generates the canvas class I'm using that inherits from different classes depending on the version of API being used. Namespacing your Javascript post provides a good starting point for those who may need get familiar with this approach.

Let's look at the differences between the APIs and how they can be resolved. The most impatient can scroll to the end of the post to see the result.

1. Map initialization:

if (version == 2) {
  map = new google.maps.Map2(el);
  map.addControl(new google.maps.SmallZoomControl3D());
  map.setCenter(new google.maps.LatLng(lat, lng), zoom);
}
else {
  map = new google.maps.Map(el, {
    zoom: zoom,
    center: new google.maps.LatLng(lat, lng),
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    mapTypeControl: false,
    scaleControl: false,
    navigationControlOptions: {style: google.maps.NavigationControlStyle.SMALL}
  });
}

Both versions use same namespace (google.maps), but they differ in how maps are created and initialized: v2 is using Map2() and setCenter() methods, whereas v3 is using one Map() call that accepts an object with all map settings as an additional parameter.

2. Adding overlay to the map:

(version == 2 ? map.addOverlay(canvasLayer) : canvasLayer.setMap(map));

v2 is using map.addOverlay() and v3 is using setMap() method of the object being added.

3. Overlay class to inherit from:

CanvasTileLayerOverlay.prototype = 
  (version == 2 ? new google.maps.Overlay() : new google.maps.OverlayView());

v2 has google.maps.Overlay class (same as GOverlay) and v3 provides OverlayView that exposes (almost) the same functionality. I set the prototype depending on which version is being used (which is passed as a parameter). It would be convenient to be able to retrieve the version number in some way from the API, but I couldn't find any way to do that.

4. Classes/method to use to get the map container and the current projection:

var div = (version == 2 ? map : this.getProjection()).fromLatLngToDivPixel(center);
var c = (version == 2 ? map.getContainer() : map.getDiv());

getContainer() method got replaced with getDiv(), but they both return a DOM object that contains the map. To convert LatLng coordinates to (div) pixel coordinates v2 provided the fromLatLngToDivPixel() method on the map object, but in v3, this method is in the projection object that can be retrieved from the overlay itself (this in this example refers to the overlay object itself).

5. Getting the pane to attach the element to:

(version == 2 ? this._map.getPane(google.maps.MAP_MAP_PANE) : this.getPanes().mapPane)
  .appendChild(this._container);

Notice that G_MAP_MAP_PANE got changed to google.maps.MAP_MAP_PANE in v2 because of the namespace change, but v3 is using the getPanes() method and specific pane types. They both return the DOM element to attach to.

6. Methods that get triggered by various events:

initialize became onAdd, remove became onRemove, and redraw is simply draw in v3. Also notice that parameters for some methods have changed too: for example, initialize gets the map object as a parameter in v2, but onAdd doesn't have any parameters in v3 (as documented).

7. Events and event methods:

The event model had several changes in the version overhaul: 1) the namespace (GEvent/google.maps.Event in v2 and google.maps.event in v3), 2) provided methods (for example, bind is not curently offered, but can be implemented as addListener(map, event, function(){return object.method.apply(object, arguments)}), and 3) events themselves; some events got added and some others have changed their behavior.

The most notable difference is probably that some functionality is not yet available in the new version (and some may never be, like GDownloadUrl that provides functions widely available elsewhere).

Here is the complete example that allows you to see it all in action and easily switch between the two APIs. It also remembers the map position and returns to the same position when the API is switched. Its functionality is rather simple -- it displays a grid that is aligned with map tiles -- but its logic is not quite that simple as it calculates tile positions and manipulates DOM elements to show tiles that are currently visible.

This code has been seen working in FF 3.5, IE 7 (with ExCanvas) and iPhone 3G Safari.

Leave a comment

what will you say?
(required)
(required)

About

I am Paul Kulchenko.
I live in Kirkland, WA with my wife and three kids.
I do consulting as a software developer.
I study robotics and artificial intelligence.
I write books and open-source software.
I teach introductory computer science.
I develop a slick Lua IDE and debugger.

Recommended

Close