This is the P2PU Archive. If you want the current site, go to www.p2pu.org!

Online Maps with OpenLayers

Events: changing your map and listening to your users

Nick Doiron's picture
Sun, 2011-03-20 01:09

---This section shows how to detect and respond to your users moving and zooming the map---

In programming-speak, an event is generated whenever the user moves the mouse, clicks, types a key, or does other actions, such as moving and zooming a map.  Event listeners detect and respond to these events.  A good example is the SelectControl that you added to make your map icons clickable.  These lines of code connected its events to your functions.

pointLayer.events.on({
    'featureselected': onFeatureSelect,
    'featureunselected': onFeatureUnselect
});
function onFeatureSelect( clickInfo ){
 ....
}
function onFeatureUnselect( clickInfo){
 ....
}

Suppose we want a map which starts out with a low-detail map, and changes to the OpenStreetMap layer when the user has zoomed in.  Start with this map, which is set up a little differently than other examples.  It uses a simple WMS layer, and a selector button in the top right lets you switch to OpenStreetMap.
http://jsfiddle.net/UAxun/120/

We need to create an event listener, so that our code will respond when the user zooms in.  Use the documentation library at http://dev.openlayers.org/docs/files/OpenLayers/Map-js.html to research the event type which we should look for.  Under EVENT_TYPES, the map object has an event called zoomend.

We connect the OpenLayers map's event to our own zoomChanged function with this line of code.

map.events.register( "zoomend", map, zoomChanged );
function zoomChanged ( ) {
   alert( " zoom has changed " );

Adding this to your jsFiddle example should give you a popup each time you zoom the map.  But to make it useful, we need to have it act on the map.  There is no additional information given by this event, so we will need to call map.getZoom() to see what the new zoom level is.  At zoom level 7 (zooming in three times from my start view) there wasn't any new detail on the basic map, so I'll have that be the level to change layers.  The first change I made to zoomChanged looked liked this:

function zoomChanged ( ) {
    if ( map.getZoom ( ) >= 7 ) {
        // use setVisibility function available for all layers:  http://dev.openlayers.org/apidocs/files/OpenLayers/Layer-js.html
        osm.setVisibility ( true );
        wms.setVisibility ( false );
    }

This works once, but then you can't zoom in anymore.  OpenLayers is insistent on there being a base layer, and it assumes wms is the base layer.  When we swap layers, it refuses to follow our interactions with OpenStreetMap.  Referring back to the API docs, map has a function called setBaseLayer.  Let's use that to rewrite zoomChanged.

function zoomChanged ( ) {
    if ( map.getZoom ( ) >= 7 ) {
        // use setVisibility function available for all layers:  http://dev.openlayers.org/apidocs/files/OpenLayers/Layer-js.html
        osm.setVisibility ( true );
        wms.setVisibility ( false );
        map.setBaseLayer ( osm );
    }

To stop this from running every time the user zooms in, let's use another if statement to try changing layers only if wms.getVisibility() is still true.

function zoomChanged ( ) {
    if ( map.getZoom ( ) >= 7 ) {
       if ( wms.getVisibility()  ) {
            // use setVisibility function available for all layers:  http://dev.openlayers.org/apidocs/files/OpenLayers/Layer-js.html
            osm.setVisibility ( true );
            wms.setVisibility ( false );
            map.setBaseLayer ( osm );
       }
    }

And the layer should change back when the user zooms out.  If zoom is not >= 7, do the opposite of what you did to activate the OpenStreetMap layer.

function zoomChanged({
    zoom map.getZoom();
    if (zoom >= 7{
        if (wms.getVisibility(){
            osm.setVisibility(true);
            wms.setVisibility(false);
            map.setBaseLayer(osm);
        }
    }
    else {
        if (osm.getVisibility(){
            osm.setVisibility(false);
            wms.setVisibility(true);
            map.setBaseLayer(wms);
        }
    }
}

The LayerSwitcher control doesn't keep up with these changes, and is no longer needed because the map changes layers on its own.  Remove it from your map.

http://jsfiddle.net/UAxun/121/

You can use other events, such as moveend , to redraw parts of your map and load more information when the user moves to a new area.  Many websites use this event so that the page's sidebar will only show information about places which are visible on your map ( Yelp.com is a great example of this for restaurant search ).  You could also use this to keep users from moving the map too much and losing the site which you've mapped.