Changing mouse pointer style in OpenLayers.

Posted by – Sunday 2010-10-17

In this post we will see how to change mouse pointer style in a OpenLayers (version 2.9.1) based map viewer depending on the control currently active. This is a feature frequently demanded by end users who want, for example, that the mouse pointer becomes a hand when the drag control is active.

The first section is a brief introduction to mouse pointer styles in web browsers. In the second section we will see how change the mouse pointer style. Finally, in the third section we will see how to supply some eye candy by (a) Creating custom mouse pointers in a Ubuntu Linux environment and (b) Using them in OpenLayers.

1. Mouse pointer styles.

In a web browser the mouse pointer style can be changed by setting the value of the CSS cursor property of document.body.style. There are a number of predefined styles. For example, the ‘default’ style shows the usual arrow, and the ‘wait’ style – used to indicate that the program is busy – shows an hourglass or a loading indicator [1]; actual mouse styles are web browser dependent.

Custom mouse pointer styles can be created and used in web browsers. The custom mouse pointer must be stored as a raster image, and uploaded to the server. The most usual formats are .ani (animated cursors) and .cur (not animated cursors) [2], both supported by Microsoft’s web browsers and sometimes by its non-Microsoft counterparts.

2. Changing mouse pointer style depending on OpenLayers active control.

Let’s suppose that our OpenLayers based map viewer has two controls that can be selected by users: DragPan and ZoomBox. When the DragPan control is active, mouse pointer style will be a hand. When the ZoomBox control is active, mouse pointer style will be a cross. Since these controls belong to a panel, it is not possible that both are simultaneously active: if one of them is active, the another one will be inactive.

The JavaScript code shown in this section uses the OpenLayers (version 2.9.1) and Prototype (version 1.6.1) [3] libraries.

var mousePointerStyle = 'default';

var MOUSE_POINTER_STYLES = {
	'OpenLayers.Control.DragPan': 'move',
	'OpenLayers.Control.ZoomBox': 'crosshair',
	'none': 'default'
}

var mapOptions = {
	'units': 'm',
	'numZoomLevels': 10,
	'projection': 'epsg:23029',
	'maxExtent': new OpenLayers.Bounds(580000, 4688000, 680000, 4850000),
	'maxResolution': 200,
	'theme': '/path/to/theme',
	'controls': []
};
map = new OpenLayers.Map('map', mapOptions);

var dragPan = new OpenLayers.Control.DragPan({'title': 'pan'});
var zoomBox = new OpenLayers.Control.ZoomBox({'title': 'zoom'});
var navToolBar = new OpenLayers.Control.Panel({'div': $('basic-controls')});
navToolBar.addControls([dragPan, zoomBox]);
navToolBar.defaultControl = dragPan;

map.addControl(navToolBar);
map.addControl(new OpenLayers.Control.PanZoomBar());

setMousePointerSwitcher();

The variable mousePointerStyle is global and stores the current mouse pointer style. The object MOUSE_POINTER_STYLES stores the mouse pointer styles used for each control. The DragPan and ZoomBox control icons are displayed in a div whose id is ‘basic-controls’, which would look like the picture shown in figure 1 (the actual look will depend on the used OpenLayers theme).

OpenLayers DragPan and ZoomBox controls
figure 1

The function setMousePointerSwitcher registers the needed events to get the mouse pointer style changed when the appropiate events are triggered. Let’s see its code:

function setMousePointerSwitcher() {
	var panelControls = 
         map.getControlsBy('div', $('basic-controls'))[0].controls;
	for (var i = 0; i < panelControls.length; i = i + 1) {
		var c = panelControls[i];
		c.events.register('activate', c, function() {
				mousePointerStyle = MOUSE_POINTER_STYLES[this.CLASS_NAME];
		});
	}

	// Change mouse pointer style when it is over the map area.
	$('map').observe('mouseover', function() {
		document.body.style.cursor = mousePointerStyle;
	});

	// When not over the map area, mouse pointer style 
	// is the default one.
	$('map').observe('mouseout', function() {
		document.body.style.cursor = 'default';
	});
}

On user mouse click over the control icon, the 'activate' event is triggered and the listener sets the global variable mousePointerStyle to the appropiate mouse style. It must be noted that by just setting the global variable mousePointerStyle to a new value the mouse pointer style will not change. The new mouse pointer style will be only visible when the mouse pointer is over the map div (lines 41-43); out of the map div, the mouse pointer style will always be 'default' (lines 47-49), no matter which control is active.

The previous behaviour can be refined. Which mouse pointer style is shown when the mouse pointer is over the pan zoom bar? In our case the 'move' style because this control's div is inside map's div. If we want that the mouse pointer style is 'default', we can register the 'mouseover' event on the PanZoomBar control's div and set a handler function that changes the mouse pointer style to 'default' [note 1]:

var panZoomBarDivId = 
     map.getControlsByClass('OpenLayers.Control.PanZoomBar')[0].div.id;

$(panZoomBarDivId).observe('mouseover', function(event) {
		document.body.style.cursor = 'default';

		// If the propagation of the mouseover event is not stopped, the
		// mouse pointer shape will be changed again to the value stored
		// in the global variable 'mousePointerStyle'.
		Event.stop(event); 
});

3. Creating and using custom mouse pointer styles.

Let's see how to create a custom mouse pointer style using a Ubuntu Linux operating system (OS). One of these custom mouse pointers can be needed, for example, to give users an uniform look and feel independently of the web browser they use. If using the mouse pointer styles provided by the web browser it can happen, for example, that the shape of the mouse pointer style 'move' is completely different in Internet Explorer and Firefox, both running on a Microsoft Windows OS: respectively, four arrows separated 90 degrees and a hand. This can also happen when running the same web browser in different OSes.

First, create your custom mouse pointer style using your fauvorite image editor and save it in a PNG format; in our example, its name will be 'drag-hand.png'. The following image settings have worked for me: image size 32x32 pixels and 256 colors.

Next step is converting the PNG image to the .cur format. In Ubuntu Linux this can be done by using icotools [4]. If not available in your computer, you can install icotools by using apt-get:

$ sudo apt-get install icoutils

Once icotools is installed, the conversion is done by using the icotool command:

$ icotool /path/to/drag-hand.png -c -o /path/to/drag-hand.cur

After you have uploaded the .cur file to your server, you can use it with a JavaScript code like this:

document.body.style.cursor = url('/path/to/drag-hand.cur');

Please, remember that, as said in section 1, the .cur format is not supported by all web browsers, so do not expect this solution will always work.


notes

[note 1] The following code did not worked for me in Internet Explorer 7:

var panZoomBarCtrl = 
      map.getControlsByClass('OpenLayers.Control.PanZoomBar')[0];
panZoomBarCtrl.observe('mouseover', function(event) {
  	document.body.style.cursor = 'default';
 	Event.stop(event);
});


references

[1] Good references of mouse pointer styles can be found at http://www.javascriptkit.com/dhtmltutors/csscursors.shtml and http://www.webpelican.com/blog/2006/04/18/css-cursor-property-values/.

[2] Information about MS Windows icons can be found at http://en.wikipedia.org/wiki/ANI_(file_format) and http://en.wikipedia.org/wiki/ICO_(icon_image_file_format).

[3] Prototype library web page: http://prototypejs.org/

[4] Icoutils web page: http://www.nongnu.org/icoutils/

1 Comment on Changing mouse pointer style in OpenLayers.

Respond

  1. Suraj says:

    Thanks for this blogpost. It’s really a good and much helpful work! :)

Respond

Comments

Comments