Openlayers and Mobile Devices

25 Nov 2009 . . Comments

#openlayers #mobile #gis

After some really good conversations last week at the Institute on Enabling Geospatial Scholarship about mobile devices and mapping as an interpretive device, I mocked up a quick page to see how OpenLayers looked on the Safari mobile browser. The theory to test out here was that you could pretty easily pull up your current location and plot your (approximate) location on a historic map (or any map for that matter) without having to install an application (like Old Map App). There are various hurdles in higher education to actually releasing software application through vendors like Apple’s App Store (restrictions on individual employees entering into contractual agreements), so we thought we’d explore using the browser to provide some of this functionality to users.

We have a few historic maps from our McGregor collection available through our Geoserver installation, so I looked up their layer ids and manually added them into a page with OpenLayers. Nothing fancy here, just a test to see what it looks like.

var lat, long layer;
var zoom = 10;

var lat, lon, layer;
 var zoom = 10;

 map = new OpenLayers.Map('map');
 map.addControl(new OpenLayers.Control.LayerSwitcher());

 layer1 = new OpenLayers.Layer.WMS("Map of the Southern States",
 "http://lat.lib.virginia.edu:8080/geoserver/gwc/service/wms",
 {layers: "McGregor:000003056_00011"}
 );
 layer2 = new OpenLayers.Layer.WMS("Nova Virginae tabula",
 "http://lat.lib.virginia.edu:8080/geoserver/gwc/service/wms",
 {layers: "McGregor:000003482_00011"}
 );
 layer3 = new OpenLayers.Layer.WMS("A map of the most inhabited part of Virginia",
 "http://lat.lib.virginia.edu:8080/geoserver/gwc/service/wms",
 {layers: "McGregor:000003012_st1"}
 );
 layer4 = new OpenLayers.Layer.WMS("Carte de la campagne en Virginie du Major General Mis. de la Fayette",
 "http://lat.lib.virginia.edu:8080/geoserver/gwc/service/wms",
 {layers: "McGregor:000003013_st1"}
 );
 layer5 = new OpenLayers.Layer.WMS("Carte de la campagne en Virginie du Major General Mis. de la Fayette",
 "http://lat.lib.virginia.edu:8080/geoserver/gwc/service/wms",
 {layers: "McGregor:000003019_00011"}
 );

 map.addLayer(layer1);
 map.addLayer(layer2);
 map.addLayer(layer3);
 map.addLayer(layer4);
 map.addLayer(layer5);

if(navigator.geolocation){
 navigator.geolocation.getCurrentPosition(function(position){
 lat = position.coords.latitude;
 lon = position.coords.longitude;
 map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);

 var vectorLayer = new OpenLayers.Layer.Vector("Overlay");
 var feature = new OpenLayers.Feature.Vector(
 new OpenLayers.Geometry.Point(lon, lat),
 {some:'data'},
 {externalGraphic: 'http://geocoder.ca/marker.png', graphicHeight: 64, graphicWidth: 48});
 vectorLayer.addFeatures(feature);
 map.addLayer(vectorLayer);
 });
 }

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

This actually worked surprisingly well the first time I launched it. With Firefox 3.5 I tested it on my laptop. At first I wasn’t using the geowebcache we had set up, so it was a bit slow. I changed to the geowebcache WMS service and things in the browser were noticeably faster.

At lunch, I handed an iPhone to Schuyler Erle who’s first instinct was to try to drag things around and zoom-in and out. Well, there was a fail as the controls you normally use in OpenLayers were far too small to actually be useful and it just didn’t feel right.

I then attempted to add in a touchHandler function to help with the interactions from the user. I found Ross Boucher’s post “iPhone Touch Events in JavaScript” and used his code to get the sliding working:

function touchHandler(event)
{
   var touches = event.changedTouches,
   first = touches[0],
   type = "";

   switch(event.type)
   {
     case "touchstart": type = "mousedown"; break;
     case "touchmove":  type="mousemove"; break;
     case "touchend":   type="mouseup"; break;
     default: return;
 }

 // initMouseEvent(type, canBubble, cancelable, view, clickCount,
 // screenX, screenY, clientX, clientY, ctrlKey,
 // altKey, shiftKey, metaKey, button, relatedTarget);

    var simulatedEvent = document.createEvent("MouseEvent");
    simulatedEvent.initMouseEvent(type, true, true, window, 1,
    first.screenX, first.screenY,
    first.clientX, first.clientY, false,
    false, false, false, 0/*left*/, null);

    first.target.dispatchEvent(simulatedEvent);
    event.preventDefault();
 }

 document.addEventListener("touchstart", touchHandler, true);
 document.addEventListener("touchmove", touchHandler, true);
 document.addEventListener("touchend", touchHandler, true);
 document.addEventListener("touchcancel", touchHandler, true);

Now the scrolling worked, but you could no longer zoom into the map (and we want real zoom, not just making the image bigger). I haven’t found a fix for this yet, but I have to say that this is a kind of cool way of interacting with these materials.

Something I need to talk with Joe about next week making your location a query to Geonetwork and then using the top n maps returned to build this interface. It’s a little like a coverage map for your current location.