Touch Gesture Support for OpenLayers
OpenLayers is a Javascript framework that implements something similar to the Google Maps "pan and zoom" capability over map tile sets. It is a very flexible framework and it works quite well in the desktop browser. However, it is basically unusable in its default form on mobile touch-based devices such as the iPhone, iPad and Android devices. Fortunately, murrayhking over at the Geo-Mobile blog pointed me toward a solution for this.
Basically, all you have to do is include touch.js so you get the TouchHandler class and then instantiate one with your map like this:
this.touchhandler = new TouchHandler( map, 4 );
This invokes direct gesture support on the div containing your map and makes the map scroll as you would expect.
For some reason, scrolling is much faster on my iPhone than on my iPad. Things are fairly smooth on my Android device (Nexus One) as well so I don't know what is up with that.
An example speaks 1,000 words so I made a working demo using the Open Street Map tiles here:
http://anders.com/touchmaps
Give it a try and let me know how it can be improved.
UPDATE: they have added touch support to openlayers now. Take a look at:
http://www.openlayers.org/dev/examples/mobile-navigation.html
Comments (18)
zac spitzer from melbourne australia
On my nexus one (froyo), it pans ok, with a bit of a lag, but pinch zoom doesn't work
Julian from Germany
Thank you, just what I was looking for. I swapped the zoomIn()/zoomOut() function calls to get the natural iPhone pinch zoom behaviour.
Julian from Germany
I am using markers with the OpenLayers-PopUp-Feature. It´s event is registered on the "mousedown"-event of the marker. With the original "touch.js", the PopUp won´t show as the touchstart-function will stop propagating the event. To overcome this I commented out the "event.preventDefault()" call in the touchstart-function. Now it works. Do you see any issue with this approach? Thanks for your comment. Regards.
Anders from Cambridge, MA
Julian: Thanks for the suggestion, I've incorporated it in the touch.js linked from this site. Much appreciated.
Anders from Cambridge, MA
Zac: Thanks. Indeed, there seems to be a problem with pinch-zoom on Android using Froyo on the Nexus One. Both iOS and Android rely on WebKit so I would assume the same touch events would fire but as pinch-zoom is so new to Android, either it doesn't fire the same javascript event or that part is broken in Froyo. I'll have to do some further testing to figure this out. Thanks again for pointing it out. I'll post here when I find a solution.
PAD from Farnborough / UK
I tried to view your map website on my HTC Desire (Android 2.1). None of the touch events worked for me, in fact the map just appeared to be a hyperlink and refreshed the page.
Maurice from Amsterdam
Thank you for explaining how to include multi touch in Openlayers. While testing the example you gave us I also found out that you included GPS capabilities! How did you do that? It looks like I have to do something with ¨navigator.geolocation¨. Do I have to install something on my server for that?
Anders from Cambridge, MA
PAD: That is clearly an issue. The map should work as if you were using a desktop browser. Maybe they changed some of the events in your build. As I don't have an HTC Desire, is there any chance you can figure out what events fire for touch gestures? I'm not able to replicate this issue.
Anders from Cambridge, MA
Maurice: Browsers that support it (particularly on mobile devices) can deliver location data to JavaScript applications. I do that by testing for the existence of navigator.geolocation in the DOM. If that exists, then the browser supports geolocation. Next, I do:
navigator.geolocation.watchPosition( positionUpdate, positionUpdateFail );
which tells the browser to run the function "positionUpdate" passing in the position every time we get a new fix. (typically once per second) We will also run the function "positionUpdateFail" passing in the error if there is a problem.
Each time positionUpdate runs, I update the location of the "myLocation" blue dot and recenter the map. There is more code around that to enable turning that feature on or off but that is the guts of it.
No server-side components are necessary, this is strictly a browser capability.
David Hine from Mission Beach/Queensland/ Australia
My HTC Desire loaded the map. Zooming in worked partly. The text got larger and the map zoomed in. But the map area got narrower and longer. Scrolling down got a long column of text and map image/tiles
I hope you'll continue with the project. Its a welcome development.
David Bennett from Kansas City, MO, USA
_Please_ star this issue on the Anroid bug list:
http://code.google.com/p/android/issues/detail?id=11909
We need to raise awareness of the lack of support for multiple javascript touch events which enables pinch zoom.
Benoît Quartier from Lausanne / VD / Switzerland
Hi we did some work on this and will continue. You can have a look at http://www.camptocamp.com/fr/blog/2010/12/mobile-web-gis/
Some tickets have been opened in the OpenLayers trac (see ticket #3000).
As D. Bennett wrote, please, star the issue on the Android bug list!
Timo from Perth / WA / Australia
Good work. I found these guys and they don't seem to have so much problems with delays in panning (much more responsive!)
How is the progress with your project going?
Anders Brownworth from Cambridge,MA
Thanks for the link, Timo. That panning is very good but I don't see pinch zoom support. Shouldn't be too hard to add I would guess. The actual pan and zoom code I'm using here is from OpenLayers - I'm just calling it from touch gestures rather than mouse clicks. I'm going to rip this apart and see if I can figure out why their pan is so much smoother though. Thanks.
Laurent MEAR from Brest, France
Thanks for your work. I use your "jtouch.js" library on a iphone4 and it works fine.
Sven Laqua from United Kingdom
Thanks so much for this post, it helped a lot to speed things up with getting the map interactions to work on a XOOM that we're prototyping for right now.
I have one more hint though, the touch examples on OpenLayers.org you point to are all nice, but make use of a custom-version openlayers.mobile.js, which does not support adding Markers from what I can tell - at least I failed pretty badly and also failed to find the relevant references in the js code...
So after a bit of digging I noticed the latest release RC1 of OpenLayers.js (2.11), which combines both touch support and other aspects like markers... people may want to go with that file rather than the dedicated ...touch.js as it seems limited.
anyway, thanks for the great post again!
Sven.
Charles-Henri Lison from Melbourne
Hi Mate,
My name is Charles, 24yo from Australia.
I am working on a system who's using Open Layer and unfortunately It's really hard to include Open Layer Mobile: a lot of incompatibilities. Indeed the previous Dev. Team integrated different customized functions and of course, the documentation related to the dev. doesn't exist.
So touch.js is really good when you want to save time in the dev. However, there is an issue with these lines:
map.constructor.prototype['limitZoomOut'] = function( ) {
if ( this.getZoom( ) <= 2 ) {
return true;
}
return false;
};
All my scripts crashed for some reasons, but if I comment these lines everything works fine. So It might be need to be patched.
Cheers and thank you again.
Charles
Anders from Cambridge, MA
Charles: What error do you get? What browser / OS combination are you using?
Leave a Comment
To create links in comments:
[link:http://anders.com/] becomes http://anders.com/
[link:http://anders.com/|Anders.com] becomes Anders.com
Notice there is no rel="nofollow" in these hrefs. Links in comments will carry page rank from this site so only link to things worthy of people's attention.