Having looked at openlayers, we had problems with performance on mobile devices. A latency problem especially when dragging/panning the map.
A new framework has recently appeared that addresses that issue called touchMapLite.
http://wiki.openstreetmap.org/wiki/TouchMapLight
Its very lightweight at (35k) and based on the pano.js library http://code.google.com/p/panojs/.
Its in the early development stage but we were impressed with it.
Conversely, Openlayers 2.8 is about 700k, although you can optimise this by using a build script to specify only the javascript files your setup requires. For us, that typically reduces our openlayers lib to about half the size.
Of course you are losing a lot of potential functionally when compared with openlayers and it has great documentation. If you just care about rendering performance and maybe basic use of markers then this small library might be the way to go. There isn’t much in the way of documentation with touchMapLite although there are some helpful samples that come with the source.
Another caveat is the type of map source you are displaying for example one source we are using is in British National Grid EPSG:27700 projection with units in meters.
So we had to override some fairly low level functions to cope with this projection. We had to use our own javascript utilities (the coordamatic library) for unit and projection changes to get it working eg
projection changes
touchMapLite.js latlon2pan: function(lat,lon) { //use uk national grid var coords ; coords = this.natgrid.toLocalSystem(lat, lon); var northings = coords[0]; var panNGLat = 1-(northings/this.EXTENT); var eastings = coords[1]; var panNGLon = eastings/this.EXTENT; return {x: panNGLon, y:panNGLat}; }
NOTE. So the actual units range required by the underlying rendering engine are 0.0 – 1.0
so x=0.5,y=0.5 would give you the centre of the map near equatorial guinea.
unit changes
touchMapLite.tileUrlProvider.WMS.js resolutionAtZoomLevel: function(zoom){ return this.initialResolution / Math.pow(2,zoom); } pixelsToMetersAtZoom: function(ptPixels, zoom) { var resolution = this.resolutionAtZoomLevel(zoom); var ptMeters = ptPixels * resolution; return ptMeters; }, //create the wms bounding box //convert google y to TMS = (2**zoom - 1) - tygoogle var ytms =(Math.pow(2, zoom) -1) – yIndex; var bbLeftMeters = this.pixelsToMetersAtZoom(xIndex * this.tileSize, zoom ); var bbRightMeters = this.pixelsToMetersAtZoom( (xIndex+1) * this.tileSize, zoom ); var bbTopMeters = this.pixelsToMetersAtZoom( (ytms+1) * this.tileSize, zoom ); var bbBottomMeters = this.pixelsToMetersAtZoom( ytms * this.tileSize, zoom );
So we had a quite bit of work to get one of our map sources to work with it.
in openlayers you can simply this declare this at map construction time.
var map = new OpenLayers.Map('map', { projection: new OpenLayers.Projection("EPSG:27700"), units: "m", maxExtent: bounds, resolutions: [2000,400,100,50,25,10.16,5,2.5,0.625]});
However this might not be a very common use case and if you are just using common map sources …
Google,TMS and WMS,lat, long, Spherical Mercator projection it should work out the box.
However the performance difference is noticeable between the two libs. touchMapLite gives a user experience closer to a native application.
Potential off-line application?
There is code in touchMapLite that uses some HTML5 storage features. HTML5 canvas is used to base64 requested images and store them in a client-side SQL database. This would be a nice feature for an off-line application for use when travelling to remote parts of the country for field trips, hillwalking etc. I suppose you could use a cache.manifest instead when you are sure of the locations of your tile images but this technique would lose the flexibility of the canvas/sql approach.
fetchTileFromCache: function(image,z,x,y,src) { var tileObject = new Object; tileObject.image = image; tileObject.provider = this.id; tileObject.x = x; tileObject.y = y; tileObject.z = z; tileObject.src = src; tileObject.tiles = this; if(this.db){ // && document.getElementById('cache') && document.getElementById('cache').checked this.db.transaction(function (tx) { tx.executeSql("SELECT data FROM tiles WHERE provider = ? AND x = ? AND y = ? AND z = ?", [tileObject.provider, tileObject.x, tileObject.y, tileObject.z], function(tx, result) { if(!result.rows.length){ tileObject.tiles.populateCache(tileObject); } else { tileObject.image.src = result.rows.item(0).data; } }, function(tx, error) { tileObject.tiles.populateCache(tileObject); }); }); } else { image.src = src; } }
Here is our example of using touchMapLite using a WMS map source.
http://mab.edina.ac.uk/geomobile-test/osopen.html
It uses the ordnance survey products stack which has been recently been made freely available. https://www.ordnancesurvey.co.uk/opendatadownload/products.html.
We have used a local map-server installation to serve up the osopen stack.
[…] mapping app using OpenLayers. We also created a mobile app using this datasource, as desribed in a previous post on the TouchMapLite […]
By: OpenStream WMS service for ac.uk | Geo-Mobile Blog on September 27, 2010
at 2:23 pm
This is pretty slick… I’m going to give it a shot with some of my mapdata.
By: Chris Stuber on December 6, 2010
at 7:55 am
can i create this open layer application in iphone without using phone gap. i just want to use this open layer application which is build from my own xcode native codes? can i do that thing in xcode.
please reply me.
By: Jaimin on August 11, 2011
at 6:56 am
You could probably embed a UIWebView component in your app and display your openlayers map within that keeping you native for the app store and the likes.
By: murrayhking on August 11, 2011
at 1:40 pm
Pretty great post. I just stumbled upon your weblog and wanted to
say that I have really loved surfing around your
weblog posts. In any case I will be subscribing in your
feed and I’m hoping you write once more soon!
By: Frederick on June 9, 2013
at 8:31 am