Monday, 16 March 2015

Synchronizing zoom and pan among multiple map tiles using OpenLayers

What can you do if you have more than two or more maps in a html page and you want to synchronize their pan and zoom, so they all show the same location, at the same scale, each time you look at them?
Such a thing is useful if you want to compare two map sources or you want to display a street map and the aerial photo of the same location. Here is a tip on how to do this using openlayers. I have tested it in Geoserver.
At first it has to be defined where the maps will be shown. A way to do this is to divide the screen equally and give a piece to each map. A simple way to do this is for two maps is to add the following code in the html body

<div style="width:100%; height:50%" id="map"></div>

Then, two (or more) maps have to be defined as variables; one for each map source. The variables need to be initialized as usually (with or without additional options) and the layers for each map must be added.

var map1;
var map2;
map1 = new OpenLayers.Map('map', options);
map2 = new OpenLayers.Map('map', options);
map1.addLayer(myfirstlayer);
map2.addLayer(mysecondlayer);


For the two maps to appear simultaneously in the html page, it is necessary to add controls and define the map center or extend for each one separately. Somehow like this

map1.addControl(new OpenLayers.Control.Navigation());
map1.setCenter( new OpenLayers.LonLat(35.000000,27.00000).transform( new OpenLayers.Projection("EPSG:4326"),map1.getProjectionObject()), 17);

map2.addControl(new OpenLayers.Control.Navigation());
map2.setCenter( new OpenLayers.LonLat(35.000000,27.00000).transform( new OpenLayers.Projection("EPSG:4326"),map2.getProjectionObject()), 17);


In order to achieve synchronization in each map there must be registered listeners for the pan and zoom events and some functions that create new zoom and pan events. For the pan events the “moveend” listener should be used and for the zoom events the “zoomend”  listener.

//Register Listeners
map1.events.register("moveend", null, mapEventM);
map1.events.register("zoomend", null, mapEventZ);
               
map2.events.register("moveend", null, mapEventM2);
map2.events.register("zoomend", null, mapEventZ2);


Each listener registered in map1 is associated with a function that manipulates the appearance of map2 and vice versa. So on a zoom event on map1, function mapEventZ passes the zoom to map2 and on a zoom event on map2 function mapEventZ2 passes the zoom parameters to map1. On a similar ways the pan events are handled.

//Functions that manipulate pan events

function mapEventM(event) {
    map2.setCenter(map1.getCenter());
}
               
function mapEventM2(event) {
    map1.setCenter(map2.getCenter());
}

               
//Functions that manipulate zoom events

function mapEventZ(event) {
    map2.zoomTo(map1.getZoom());
}
               
function mapEventZ2(event) {
map1.zoomTo(map2.getZoom());
}



http://wmsviewer-rodis.rhcloud.com/