[GIS] How to pan (rather than zoom) when using a 2-finger drag on a Mac

openlayers-2osxux

Using Mac OSX, dragging the trackpad with 2 fingers performs a scroll of the web page, equivalent to using the mouse wheel.

However, if the cursor is located within an OpenLayers map, the 2-finger drag performs a zoom-in on the map.

Is it possible to change this action to perform a pan instead of a zoom? Eg, see the ArcGIS Server JS API's behaviour on a Mac with a trackpad.

Thanks

Best Answer

There is no 'out of the box' solution for you, unless someone else out there has come up with a patch or mod.

The API Doc for OpenLayers.Control.Navigation clearly shows that the only options available to you are to either disable or enable scrolling. There was a revision made a few months ago for pinch-zoom, but that's it as far as touch pads are concerned.

I've had the same issues with my implementations of WebGL via the H5's canvas. It's not an easy solution to go about implementing due to the 'fun times' surrounding cross browser support.

If you're feeling adventureous, you can look at line 263 in the OpenLayers.Control.Navigation 'class'. You'll override the functionality with something like iScroll being careful not to interfere with the existing functionality and ruining the experience for people without a touchpad.

263     wheelChange: function(evt, deltaZ) {
       -->  // If trackpad scrolling detected.
       -->    // Do Trackpad Stuff
264    -->  var currentMapCenterXY = this.map.getCenterXY(); // Not sure if this is right
265    -->  var newMapCenterXY = this.map.getCenterXY() + iScroll.getDeltaXY(); // unsure
       -->  // Else
       -->    // Keep calm, carry on
266         newZoom = Math.max(newZoom, 0);
267         newZoom = Math.min(newZoom, this.map.getNumZoomLevels());
268         if (newZoom === currentZoom) {
269             return;
270         }
271         var size    = this.map.getSize();
272         var deltaX  = size.w/2 - evt.xy.x;
273         var deltaY  = evt.xy.y - size.h/2;
274         var newRes  = this.map.baseLayer.getResolutionForZoom(newZoom);
275         var zoomPoint = this.map.getLonLatFromPixel(evt.xy);
276         var newCenter = new OpenLayers.LonLat(
277                             zoomPoint.lon + deltaX * newRes,
278                             zoomPoint.lat + deltaY * newRes );
279         this.map.setCenter( newCenter, newZoom );

Granted, my solution above isn't the best it could be, normally you would do the detection externally and then pass in the delta, but it gives you an idea.