Articles and Tutorials

Creating Custom Map Controls Maps API V2

Version 2 of the Maps API introduces a base map control class GSControl which can be subclassed to create your own custom map controls. This example shows how the built-in text-based zoom control GSTextZoomControl is constructed.

The base GSControl class is extended using the GSUtil.extend() function:

 
GSUtil.extend(GSTextZoomControl, GSControl);

This function sets up the inheritance chain for the custom map control class so that it will inherit all methods and properties belonging to its parent class. Within the constructor function of the custom map control, the base class' constructor function is called with two parameters: a reference to the custom control class itself; and a string uniquely naming the custom map control:

 
GSTextZoomControl.baseConstructor.call(this, 'text-zoom-control');

In the constructor for GSTextZoomControl we also setup the text labels which will be displayed using an array of object literals.

GSControl requires that custom map controls define two methods: GSControl.render(), in this method the HTML DOM elements that represent the control are created and a reference to the outermost DOM element returned to the map; and GSControl.getDefaultPosition(), this method returns to the map the position in the map viewport where the control should appear. This positioning information will be overriden if another position is given when the control is added to the map.

GSControl.getDefaultPosition() returns a positioning object which specifies the corner of the map viewport in which the control should be anchored and the offset in pixels that should be applied to the control.

 
GSTextZoomControl.prototype.getDefaultPosition = function() {
return {anchor: GSControl.ANCHOR_TOP_LEFT, offset: new GSPoint(7, 7)};
};

The full code listing is shown below:

 
GSUtil.extend(GSTextZoomControl, GSControl);
 
function GSTextZoomControl(labels) {
 
// Call superclass constructor
GSTextZoomControl.baseConstructor.call(this, 'text-zoom-control');
 
this.labels = labels;
if(!this.labels) {
this.labels = [{level: 9, value: 'Region'}, {level: 7, value: 'District'},
{level: 3, value: 'Suburb'}, {level: 1, value: 'Street'}];
}
};
 
GSTextZoomControl.prototype.render = function(map) {
var element = document.createElement('div');
 
for(var i = 0, l = this.labels.length; i < l; i++) {
var link = document.createElement('a');
link.href = '#';

GSEventManager.bind(link, 'click', this, this.zoom, this.labels[i].level);
 
link.className = 'GSTextZoomControl';
link.innerHTML = this.labels[i].value;
 
element.appendChild(link);
 
if(i < l-1) {
element.appendChild(document.createTextNode(' | '));
}
}
return element;
};
 
GSTextZoomControl.prototype.getDefaultPosition = function() {
return {anchor: GSControl.ANCHOR_TOP_LEFT, offset: new GSPoint(7, 7)};
};
 
GSTextZoomControl.prototype.zoom = function(e, level) {
map.zoom(level);
GSUtil.cancelEvent(e);
};