venerdì 1 gennaio 2010

Insert custom controls on Google maps

We definitely like maps, for this reason me and Alberto decided to explore some features related to maps and we realized some sample app in order to play with a few features:
- Twitter & maps api
- Random walk on the map

The main features of these applications (use of twitter api, put the tweets and personalized marker on the map, geocoding, paged infowindows) are described in others post (cfr. How to Play with Google Maps and Twitter api & Super simple way to use Google maps api geocoding service) but here let us to explore the definition of controls on the google map.

Map's custom controls

The google map contain UI elements that allow user interaction, as pan/zoom (e.g. GLargeMapControl), a scale (e.g. GSmallZoomControl), a button that switches the view between different map types (GMapTypeControl, per default allowing to swith between Map, Satellite, Terrain, ...).
These elements, inserted directly on the map, are known as controls and they can be included in any Google Maps API application.

All the default controls (i.e. provided by the maps API) are described here but it is also possible (and even straightforward) to build a custom control by subclassing the GControl class; Custom controls are useful for any sort of user interaction and are the standard way of putting something 'in the area' of the map (e.g. to display a custom logo in the map constructing a custom control is far the simplest way).
On the HelloKitty sample we use, for example, a control on the map in order to let the user to switch on/off the visualization of the path.

Let us to describe briefly how to setup an user generated control.

The definition of a custom control is possible through assigning as prototype object an instance of the GControl object; we define the Control on the map "TrivialMapControl" as:


   TrivialMapControl = function () {}
TrivialMapControl.prototype = new GControl();

TrivialMapControl.toggleOn
= document.createElement("span");
TrivialMapControl.toggleOn.innerHTML ="Trace ON";

TrivialMapControl.toggleOff
= document.createElement("span");
TrivialMapControl.toggleOff.innerHTML ="Trace OFF";


The definition of a custom control requires te definition of two methods:
initialize(): that creates and returns a DOM element;
getDefaultPosition(): that defines and returns an object of type GControlPosition.

The following is the initialize function that we use in our sample code:


TrivialMapControl.prototype.initialize = function(map) {
var container = document.createElement("div");
//setAttribute does not work consistently
//for 'class' with IE and ... the rest of the world
container.classNode = "map_control";

this.setButtonStyle_(TrivialMapControl.toggleOff);
GEvent.addDomListener(TrivialMapControl.toggleOff,
"click",
function() {
isViewTrace = false;
container.replaceChild(TrivialMapControl.toggleOn,
TrivialMapControl.toggleOff);
});

GEvent.addDomListener(TrivialMapControl.toggleOn,
"click",
function() {
isViewTrace=true;
container.replaceChild(TrivialMapControl.toggleOff,
TrivialMapControl.toggleOn);
});

container.appendChild(TrivialMapControl.toggleOn);

var lb = document.createElement("div");

var jl = document.createElement("img");
jl.className = "trivialmap_logo";
jl.src = document.getElementById("logo_small").src;

lb.appendChild(jl);
container.appendChild(lb);

map.getContainer().appendChild(container);
return container;
}


Our prototype.initialize() method simply displays a custom logo and defines the button (with a special style), used to show or to hide the Trace of the path along the way.

Furthermore, the getDefaultPosition function:


TrivialMapControl.prototype.getDefaultPosition =
function() {
return new GControlPosition(G_ANCHOR_TOP_LEFT,
new GSize(80, 12));
}

defines the default position of the control (so the name :o) G_ANCHOR_TOP_LEFT in our sample (the others possible choices are G_ANCHOR_TOP_RIGHT, G_ANCHOR_BOTTOM_RIGHT, G_ANCHOR_BOTTOM_LEFT) and the distance from the top/left corner.

After the definition, the map control has to be added to the map container through the following instructions:


var map =
new GMap2(document.getElementById("map_canvas"), ...);
map.addControl(new TrivialMapControl());

That's all Folks !!!