diff options
Diffstat (limited to 'js/dojo-1.7.2/dojox/geo/charting/TouchInteractionSupport.js')
| -rw-r--r-- | js/dojo-1.7.2/dojox/geo/charting/TouchInteractionSupport.js | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/js/dojo-1.7.2/dojox/geo/charting/TouchInteractionSupport.js b/js/dojo-1.7.2/dojox/geo/charting/TouchInteractionSupport.js new file mode 100644 index 0000000..6e2b7cd --- /dev/null +++ b/js/dojo-1.7.2/dojox/geo/charting/TouchInteractionSupport.js @@ -0,0 +1,313 @@ +//>>built +define("dojox/geo/charting/TouchInteractionSupport", ["dojo/_base/lang","dojo/_base/declare","dojo/_base/event", "dojo/_base/connect","dojo/_base/window"], + function(lang,declare,event,connect,win) { + +return declare("dojox.geo.charting.TouchInteractionSupport",null, { + // summary: + // class to handle touch interactions on a dojox.geo.charting.Map widget + // tags: + // private + + _map : null, + _centerTouchLocation : null, + _touchMoveListener: null, + _touchEndListener: null, + _touchEndTapListener: null, + _touchStartListener: null, + _initialFingerSpacing: null, + _initialScale: null, + _tapCount: null, + _tapThreshold: null, + _lastTap: null, + _doubleTapPerformed:false, + _oneFingerTouch:false, + _tapCancel:false, + + constructor : function(/* dojox.geo.charting.Map */map,options) { + // summary: + // Constructs a new _TouchInteractionSupport instance + // map: dojox.geo.charting.Map + // the Map widget this class provides touch navigation for. + this._map = map; + this._centerTouchLocation = {x: 0,y: 0}; + + this._tapCount = 0; + this._lastTap = {x: 0,y: 0}; + this._tapThreshold = 100; // square distance in pixels + }, + + connect: function() { + // summary: + // install touch listeners + _touchStartListener = this._map.surface.connect("touchstart", this, this._touchStartHandler); + }, + + disconnect: function() { + // summary: + // disconnects any installed listeners. Must be called only when disposing of this instance + if (this._touchStartListener) { + connect.disconnect(this._touchStartListener); + this._touchStartListener = null; + } + }, + + _getTouchBarycenter: function(touchEvent) { + // summary: + // returns the midpoint of the two first fingers (or the first finger location if only one) + // touchEvent: a touch event + // returns: dojox.gfx.Point + // the midpoint + // tags: + // private + var touches = touchEvent.touches; + var firstTouch = touches[0]; + var secondTouch = null; + if (touches.length > 1) { + secondTouch = touches[1]; + } else { + secondTouch = touches[0]; + } + var containerBounds = this._map._getContainerBounds(); + var middleX = (firstTouch.pageX + secondTouch.pageX) / 2.0 - containerBounds.x; + var middleY = (firstTouch.pageY + secondTouch.pageY) / 2.0 - containerBounds.y; + return {x: middleX,y: middleY}; + }, + + _getFingerSpacing: function(touchEvent) { + // summary: + // computes the distance between the first two fingers + // touchEvent: a touch event + // returns: float + // a distance. -1 if less that 2 fingers + // tags: + // private + var touches = touchEvent.touches; + var spacing = -1; + if (touches.length >= 2) { + var dx = (touches[1].pageX - touches[0].pageX); + var dy = (touches[1].pageY - touches[0].pageY); + spacing = Math.sqrt(dx*dx + dy*dy); + } + return spacing; + }, + + _isDoubleTap: function(touchEvent) { + // summary: + // checks whether the specified touchStart event is a double tap + // (i.e. follows closely a previous touchStart at approximately the same location) + // touchEvent: a touch event + // returns: boolean + // true if this event is considered a double tap + // tags: + // private + var isDoubleTap = false; + var touches = touchEvent.touches; + if ((this._tapCount > 0) && touches.length == 1) { + // test distance from last tap + var dx = (touches[0].pageX - this._lastTap.x); + var dy = (touches[0].pageY - this._lastTap.y); + var distance = dx*dx + dy*dy; + if (distance < this._tapThreshold) { + isDoubleTap = true; + } else { + this._tapCount = 0; + } + } + this._tapCount++; + this._lastTap.x = touches[0].pageX; + this._lastTap.y = touches[0].pageY; + setTimeout(lang.hitch(this,function() { + this._tapCount = 0;}),300); + return isDoubleTap; + }, + + _doubleTapHandler: function(touchEvent) { + // summary: + // action performed on the map when a double tap was triggered + // touchEvent: a touch event + // tags: + // private + var feature = this._getFeatureFromTouchEvent(touchEvent); + if (feature) { + this._map.fitToMapArea(feature._bbox, 15, true); + } else { + // perform a basic 2x zoom on touch + var touches = touchEvent.touches; + var containerBounds = this._map._getContainerBounds(); + var offX = touches[0].pageX - containerBounds.x; + var offY = touches[0].pageY - containerBounds.y; + // clicked map point before zooming + var mapPoint = this._map.screenCoordsToMapCoords(offX,offY); + // zoom increment power + this._map.setMapCenterAndScale(mapPoint.x, mapPoint.y,this._map.getMapScale()*2,true); + } + }, + + _getFeatureFromTouchEvent: function(touchEvent) { + // summary: + // utility function to return the feature located at this touch event location + // touchEvent: a touch event + // returns: dojox.geo.charting.Feature + // the feature found if any, null otherwise. + // tags: + // private + var feature = null; + if (touchEvent.gfxTarget && touchEvent.gfxTarget.getParent) { + feature = this._map.mapObj.features[touchEvent.gfxTarget.getParent().id]; + } + return feature; + }, + + _touchStartHandler: function(touchEvent){ + // summary: + // action performed on the map when a touch start was triggered + // touchEvent: a touch event + // tags: + // private + event.stop(touchEvent); + this._oneFingerTouch = (touchEvent.touches.length == 1); + this._tapCancel = !this._oneFingerTouch; + // test double tap + this._doubleTapPerformed = false; + if (this._isDoubleTap(touchEvent)) { + //console.log("double tap recognized"); + this._doubleTapHandler(touchEvent); + this._doubleTapPerformed = true; + return; + } + // compute map midpoint between fingers + var middlePoint = this._getTouchBarycenter(touchEvent); + var mapPoint = this._map.screenCoordsToMapCoords(middlePoint.x,middlePoint.y); + this._centerTouchLocation.x = mapPoint.x; + this._centerTouchLocation.y = mapPoint.y; + // store initial finger spacing to compute zoom later + this._initialFingerSpacing = this._getFingerSpacing(touchEvent); + // store initial map scale + this._initialScale = this._map.getMapScale(); + // install touch move and up listeners (if not done by other fingers before) + if (!this._touchMoveListener) + this._touchMoveListener = connect.connect(win.global,"touchmove",this,this._touchMoveHandler); + if (!this._touchEndTapListener) + this._touchEndTapListener = this._map.surface.connect("touchend", this, this._touchEndTapHandler); + if (!this._touchEndListener) + this._touchEndListener = connect.connect(win.global,"touchend",this, this._touchEndHandler); + }, + + _touchEndTapHandler: function(touchEvent) { + // summary: + // action performed on the map when a tap was triggered + // touchEvent: a touch event + // tags: + // private + var touches = touchEvent.touches; + if (touches.length == 0) { + + // test potential tap ? + if (this._oneFingerTouch && !this._tapCancel) { + this._oneFingerTouch = false; + setTimeout(lang.hitch(this,function() { + // wait to check if double tap + // perform test for single tap + //console.log("double tap was performed ? " + this._doubleTapPerformed); + if (!this._doubleTapPerformed) { + // test distance from last tap + var dx = (touchEvent.changedTouches[0].pageX - this._lastTap.x); + var dy = (touchEvent.changedTouches[0].pageY - this._lastTap.y); + var distance = dx*dx + dy*dy; + if (distance < this._tapThreshold) { + // single tap ok + this._singleTapHandler(touchEvent); + } + } + }),350); + } + this._tapCancel = false; + + } + }, + + _touchEndHandler: function(touchEvent) { + // summary: + // action performed on the map when a touch end was triggered + // touchEvent: a touch event + // tags: + // private + event.stop(touchEvent); + var touches = touchEvent.touches; + if (touches.length == 0) { + // disconnect listeners only when all fingers are up + if (this._touchMoveListener) { + connect.disconnect(this._touchMoveListener); + this._touchMoveListener = null; + } + if (this._touchEndListener) { + connect.disconnect(this._touchEndListener); + this._touchEndListener = null; + } + } else { + // recompute touch center + var middlePoint = this._getTouchBarycenter(touchEvent); + var mapPoint = this._map.screenCoordsToMapCoords(middlePoint.x,middlePoint.y); + this._centerTouchLocation.x = mapPoint.x; + this._centerTouchLocation.y = mapPoint.y; + } + }, + + _singleTapHandler: function(touchEvent) { + // summary: + // action performed on the map when a single tap was triggered + // touchEvent: a touch event + // tags: + // private + var feature = this._getFeatureFromTouchEvent(touchEvent); + if (feature) { + // call feature handler + feature._onclickHandler(touchEvent); + } else { + // unselect all + for (var name in this._map.mapObj.features){ + this._map.mapObj.features[name].select(false); + } + this._map.onFeatureClick(null); + } + }, + + _touchMoveHandler: function(touchEvent){ + // summary: + // action performed on the map when a touch move was triggered + // touchEvent: a touch event + // tags: + // private + + // prevent browser interaction + event.stop(touchEvent); + + // cancel tap if moved too far from first touch location + if (!this._tapCancel) { + var dx = (touchEvent.touches[0].pageX - this._lastTap.x), + dy = (touchEvent.touches[0].pageY - this._lastTap.y); + var distance = dx*dx + dy*dy; + if (distance > this._tapThreshold) { + this._tapCancel = true; + } + } + var middlePoint = this._getTouchBarycenter(touchEvent); + // compute map offset + var mapPoint = this._map.screenCoordsToMapCoords(middlePoint.x,middlePoint.y), + mapOffsetX = mapPoint.x - this._centerTouchLocation.x, + mapOffsetY = mapPoint.y - this._centerTouchLocation.y; + // compute scale factor + var scaleFactor = 1; + var touches = touchEvent.touches; + if (touches.length >= 2) { + var fingerSpacing = this._getFingerSpacing(touchEvent); + scaleFactor = fingerSpacing / this._initialFingerSpacing; + // scale map + this._map.setMapScale(this._initialScale*scaleFactor); + } + // adjust map center on barycentre + var currentMapCenter = this._map.getMapCenter(); + this._map.setMapCenter(currentMapCenter.x - mapOffsetX, currentMapCenter.y - mapOffsetY); + } +}); +}); |
