diff --git a/src/objectliterals.exports b/src/objectliterals.exports index 8e817820f2..351ef6bdcd 100644 --- a/src/objectliterals.exports +++ b/src/objectliterals.exports @@ -13,7 +13,8 @@ @exportObjectLiteralProperty ol.MapOptions.shiftDragZoom boolean|undefined @exportObjectLiteralProperty ol.MapOptions.target Element|string @exportObjectLiteralProperty ol.MapOptions.touchPan boolean|undefined -@exportObjectLiteralProperty ol.MapOptions.touchRotateZoom boolean|undefined +@exportObjectLiteralProperty ol.MapOptions.touchRotate boolean|undefined +@exportObjectLiteralProperty ol.MapOptions.touchZoom boolean|undefined @exportObjectLiteralProperty ol.MapOptions.view ol.IView|undefined @exportObjectLiteralProperty ol.MapOptions.zoomControl boolean|undefined @exportObjectLiteralProperty ol.MapOptions.zoomDelta number|undefined diff --git a/src/ol/interaction/dragpaninteraction.js b/src/ol/interaction/dragpaninteraction.js index 4281be71fb..4827c92e2f 100644 --- a/src/ol/interaction/dragpaninteraction.js +++ b/src/ol/interaction/dragpaninteraction.js @@ -80,7 +80,7 @@ ol.interaction.DragPan.prototype.handleDragEnd = function(mapBrowserEvent) { var map = mapBrowserEvent.map; var view = map.getView(); - view.setHint(ol.ViewHint.PANNING, -1); + view.setHint(ol.ViewHint.INTERACTING, -1); if (this.kinetic_ && this.kinetic_.end()) { var distance = this.kinetic_.getDistance(); @@ -111,7 +111,7 @@ ol.interaction.DragPan.prototype.handleDragStart = function(mapBrowserEvent) { } var map = mapBrowserEvent.map; map.requestRenderFrame(); - map.getView().setHint(ol.ViewHint.PANNING, 1); + map.getView().setHint(ol.ViewHint.INTERACTING, 1); return true; } else { return false; diff --git a/src/ol/interaction/touchinteraction.js b/src/ol/interaction/touchinteraction.js index c71d5997de..1e96fe7ecb 100644 --- a/src/ol/interaction/touchinteraction.js +++ b/src/ol/interaction/touchinteraction.js @@ -31,6 +31,7 @@ ol.interaction.Touch = function() { /** * @type {Array.} + * @protected */ this.targetTouches = []; diff --git a/src/ol/interaction/touchpaninteraction.js b/src/ol/interaction/touchpaninteraction.js index 0c21c78c4b..452c43159a 100644 --- a/src/ol/interaction/touchpaninteraction.js +++ b/src/ol/interaction/touchpaninteraction.js @@ -1,5 +1,4 @@ // FIXME works for View2D only -// FIXME opt_kinetic param goog.provide('ol.interaction.TouchPan'); goog.require('goog.asserts'); @@ -16,16 +15,17 @@ goog.require('ol.interaction.Touch'); /** * @constructor * @extends {ol.interaction.Touch} + * @param {ol.Kinetic=} opt_kinetic Kinetic object. */ -ol.interaction.TouchPan = function() { +ol.interaction.TouchPan = function(opt_kinetic) { goog.base(this); /** * @private - * @type {ol.Kinetic} + * @type {ol.Kinetic|undefined} */ - this.kinetic_ = new ol.Kinetic(-0.005, 0.05, 100); + this.kinetic_ = opt_kinetic; /** * @private @@ -49,7 +49,9 @@ ol.interaction.TouchPan.prototype.handleTouchMove = function(mapBrowserEvent) { goog.asserts.assert(this.targetTouches.length >= 1); var centroid = ol.interaction.Touch.centroid(this.targetTouches); if (!goog.isNull(this.lastCentroid)) { - this.kinetic_.update(centroid.x, centroid.y); + if (this.kinetic_) { + this.kinetic_.update(centroid.x, centroid.y); + } var deltaX = this.lastCentroid.x - centroid.x; var deltaY = centroid.y - this.lastCentroid.y; var view = mapBrowserEvent.map.getView(); @@ -71,8 +73,8 @@ ol.interaction.TouchPan.prototype.handleTouchEnd = var map = mapBrowserEvent.map; var view = map.getView(); if (this.targetTouches.length == 0) { - view.setHint(ol.ViewHint.PANNING, -1); - if (this.kinetic_.end()) { + view.setHint(ol.ViewHint.INTERACTING, -1); + if (this.kinetic_ && this.kinetic_.end()) { var distance = this.kinetic_.getDistance(); var angle = this.kinetic_.getAngle(); var center = view.getCenter(); @@ -87,6 +89,7 @@ ol.interaction.TouchPan.prototype.handleTouchEnd = } return false; } else { + this.lastCentroid = null; return true; } }; @@ -107,8 +110,10 @@ ol.interaction.TouchPan.prototype.handleTouchStart = view.setCenter(mapBrowserEvent.frameState.view2DState.center); this.kineticPreRenderFn_ = null; } - this.kinetic_.begin(); - view.setHint(ol.ViewHint.PANNING, 1); + if (this.kinetic_) { + this.kinetic_.begin(); + } + view.setHint(ol.ViewHint.INTERACTING, 1); return true; } else { return false; diff --git a/src/ol/interaction/touchrotateandzoominteraction.js b/src/ol/interaction/touchrotateinteraction.js similarity index 66% rename from src/ol/interaction/touchrotateandzoominteraction.js rename to src/ol/interaction/touchrotateinteraction.js index d06d6ee93d..1ce5d02a77 100644 --- a/src/ol/interaction/touchrotateandzoominteraction.js +++ b/src/ol/interaction/touchrotateinteraction.js @@ -1,6 +1,6 @@ // FIXME works for View2D only -goog.provide('ol.interaction.TouchRotateAndZoom'); +goog.provide('ol.interaction.TouchRotate'); goog.require('goog.asserts'); goog.require('ol.View'); @@ -12,8 +12,10 @@ goog.require('ol.interaction.Touch'); /** * @constructor * @extends {ol.interaction.Touch} + * @param {number=} opt_threshold Minimal angle to start a rotation. + * Default to 0.3 (radian). */ -ol.interaction.TouchRotateAndZoom = function() { +ol.interaction.TouchRotate = function(opt_threshold) { goog.base(this); @@ -23,12 +25,6 @@ ol.interaction.TouchRotateAndZoom = function() { */ this.lastAngle_; - /** - * @private - * @type {number|undefined} - */ - this.lastDistance_; - /** * @private * @type {boolean} @@ -45,23 +41,20 @@ ol.interaction.TouchRotateAndZoom = function() { * @private * @type {number} */ - this.rotationThreshold_ = 0.3; + this.threshold_ = goog.isDef(opt_threshold) ? opt_threshold : 0.3; }; -goog.inherits(ol.interaction.TouchRotateAndZoom, ol.interaction.Touch); +goog.inherits(ol.interaction.TouchRotate, ol.interaction.Touch); /** * @inheritDoc */ -ol.interaction.TouchRotateAndZoom.prototype.handleTouchMove = +ol.interaction.TouchRotate.prototype.handleTouchMove = function(mapBrowserEvent) { goog.asserts.assert(this.targetTouches.length >= 2); - var scaleDelta = 1.0; var rotationDelta = 0.0; - var centroid = ol.interaction.Touch.centroid(this.targetTouches); - var touch0 = this.targetTouches[0]; var touch1 = this.targetTouches[1]; var dx = touch0.clientX - touch1.clientX; @@ -72,19 +65,11 @@ ol.interaction.TouchRotateAndZoom.prototype.handleTouchMove = touch1.clientY - touch0.clientY, touch1.clientX - touch0.clientX); - // distance between touches - var distance = Math.sqrt(dx * dx + dy * dy); - - if (goog.isDef(this.lastDistance_)) { - scaleDelta = this.lastDistance_ / distance; - } - this.lastDistance_ = distance; - if (goog.isDef(this.lastAngle_)) { var delta = angle - this.lastAngle_; this.rotationDelta_ += delta; if (!this.rotating_ && - Math.abs(this.rotationDelta_) > this.rotationThreshold_) { + Math.abs(this.rotationDelta_) > this.threshold_) { this.rotating_ = true; } rotationDelta = delta; @@ -94,17 +79,15 @@ ol.interaction.TouchRotateAndZoom.prototype.handleTouchMove = var map = mapBrowserEvent.map; var view = map.getView(); - // rotate / scale anchor point. + // rotate anchor point. // FIXME: should be the intersection point between the lines: // touch0,touch1 and previousTouch0,previousTouch1 var viewportPosition = goog.style.getClientPosition(map.getViewport()); + var centroid = ol.interaction.Touch.centroid(this.targetTouches); centroid.x -= viewportPosition.x; centroid.y -= viewportPosition.y; var anchor = map.getCoordinateFromPixel(centroid); - // scale, bypass the resolution constraint - view.zoom_(map, view.getResolution() * scaleDelta, anchor); - // rotate if (this.rotating_) { view.rotate(map, view.getRotation() + rotationDelta, anchor); @@ -115,14 +98,12 @@ ol.interaction.TouchRotateAndZoom.prototype.handleTouchMove = /** * @inheritDoc */ -ol.interaction.TouchRotateAndZoom.prototype.handleTouchEnd = +ol.interaction.TouchRotate.prototype.handleTouchEnd = function(mapBrowserEvent) { if (this.targetTouches.length < 2) { var map = mapBrowserEvent.map; var view = map.getView(); - // take the resolution constraint into account - view.zoomToResolution(map, view.getResolution()); - view.setHint(ol.ViewHint.PANNING, -1); + view.setHint(ol.ViewHint.INTERACTING, -1); return false; } else { return true; @@ -133,15 +114,14 @@ ol.interaction.TouchRotateAndZoom.prototype.handleTouchEnd = /** * @inheritDoc */ -ol.interaction.TouchRotateAndZoom.prototype.handleTouchStart = +ol.interaction.TouchRotate.prototype.handleTouchStart = function(mapBrowserEvent) { if (this.targetTouches.length >= 2) { var view = mapBrowserEvent.map.getView(); - this.lastDistance_ = undefined; this.lastAngle_ = undefined; this.rotating_ = false; this.rotationDelta_ = 0.0; - view.setHint(ol.ViewHint.PANNING, 1); + view.setHint(ol.ViewHint.INTERACTING, 1); return true; } else { return false; diff --git a/src/ol/interaction/touchzoominteraction.js b/src/ol/interaction/touchzoominteraction.js new file mode 100644 index 0000000000..9087c5f3b4 --- /dev/null +++ b/src/ol/interaction/touchzoominteraction.js @@ -0,0 +1,98 @@ +// FIXME works for View2D only + +goog.provide('ol.interaction.TouchZoom'); + +goog.require('goog.asserts'); +goog.require('ol.View'); +goog.require('ol.ViewHint'); +goog.require('ol.interaction.Touch'); + + + +/** + * @constructor + * @extends {ol.interaction.Touch} + */ +ol.interaction.TouchZoom = function() { + + goog.base(this); + + /** + * @private + * @type {number|undefined} + */ + this.lastDistance_; + +}; +goog.inherits(ol.interaction.TouchZoom, ol.interaction.Touch); + + +/** + * @inheritDoc + */ +ol.interaction.TouchZoom.prototype.handleTouchMove = + function(mapBrowserEvent) { + goog.asserts.assert(this.targetTouches.length >= 2); + var scaleDelta = 1.0; + + var touch0 = this.targetTouches[0]; + var touch1 = this.targetTouches[1]; + var dx = touch0.clientX - touch1.clientX; + var dy = touch0.clientY - touch1.clientY; + + // distance between touches + var distance = Math.sqrt(dx * dx + dy * dy); + + if (goog.isDef(this.lastDistance_)) { + scaleDelta = this.lastDistance_ / distance; + } + this.lastDistance_ = distance; + + var map = mapBrowserEvent.map; + var view = map.getView(); + + // scale anchor point. + var viewportPosition = goog.style.getClientPosition(map.getViewport()); + var centroid = ol.interaction.Touch.centroid(this.targetTouches); + centroid.x -= viewportPosition.x; + centroid.y -= viewportPosition.y; + var anchor = map.getCoordinateFromPixel(centroid); + + // scale, bypass the resolution constraint + view.zoom_(map, view.getResolution() * scaleDelta, anchor); + +}; + + +/** + * @inheritDoc + */ +ol.interaction.TouchZoom.prototype.handleTouchEnd = + function(mapBrowserEvent) { + if (this.targetTouches.length < 2) { + var map = mapBrowserEvent.map; + var view = map.getView(); + // take the resolution constraint into account + view.zoomToResolution(map, view.getResolution()); + view.setHint(ol.ViewHint.INTERACTING, -1); + return false; + } else { + return true; + } +}; + + +/** + * @inheritDoc + */ +ol.interaction.TouchZoom.prototype.handleTouchStart = + function(mapBrowserEvent) { + if (this.targetTouches.length >= 2) { + var view = mapBrowserEvent.map.getView(); + this.lastDistance_ = undefined; + view.setHint(ol.ViewHint.INTERACTING, 1); + return true; + } else { + return false; + } +}; diff --git a/src/ol/map.js b/src/ol/map.js index 7978e829d4..f25b7908da 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -55,7 +55,8 @@ goog.require('ol.interaction.KeyboardPan'); goog.require('ol.interaction.KeyboardZoom'); goog.require('ol.interaction.MouseWheelZoom'); goog.require('ol.interaction.TouchPan'); -goog.require('ol.interaction.TouchRotateAndZoom'); +goog.require('ol.interaction.TouchRotate'); +goog.require('ol.interaction.TouchZoom'); goog.require('ol.interaction.condition'); goog.require('ol.layer.Layer'); goog.require('ol.projection'); @@ -966,13 +967,20 @@ ol.Map.createInteractions_ = function(mapOptions) { var touchPan = goog.isDef(mapOptions.touchPan) ? mapOptions.touchPan : true; if (touchPan) { - interactions.push(new ol.interaction.TouchPan()); + interactions.push(new ol.interaction.TouchPan( + new ol.Kinetic(-0.005, 0.05, 100))); } - var touchRotateZoom = goog.isDef(mapOptions.touchRotateZoom) ? - mapOptions.touchRotateZoom : true; - if (touchRotateZoom) { - interactions.push(new ol.interaction.TouchRotateAndZoom()); + var touchRotate = goog.isDef(mapOptions.touchRotate) ? + mapOptions.touchRotate : true; + if (touchRotate) { + interactions.push(new ol.interaction.TouchRotate()); + } + + var touchZoom = goog.isDef(mapOptions.touchZoom) ? + mapOptions.touchZoom : true; + if (touchZoom) { + interactions.push(new ol.interaction.TouchZoom()); } var dragPan = goog.isDef(mapOptions.dragPan) ? diff --git a/src/ol/renderer/canvas/canvasimagelayerrenderer.js b/src/ol/renderer/canvas/canvasimagelayerrenderer.js index 61eb2b898d..fa62818db7 100644 --- a/src/ol/renderer/canvas/canvasimagelayerrenderer.js +++ b/src/ol/renderer/canvas/canvasimagelayerrenderer.js @@ -78,7 +78,7 @@ ol.renderer.canvas.ImageLayer.prototype.renderFrame = var hints = frameState.viewHints; - if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.PANNING]) { + if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) { image = imageSource.getImage(frameState.extent, viewResolution); if (!goog.isNull(image)) { var imageState = image.getState(); diff --git a/src/ol/renderer/dom/domimagelayerrenderer.js b/src/ol/renderer/dom/domimagelayerrenderer.js index 7190d8c268..769b944848 100644 --- a/src/ol/renderer/dom/domimagelayerrenderer.js +++ b/src/ol/renderer/dom/domimagelayerrenderer.js @@ -66,7 +66,7 @@ ol.renderer.dom.ImageLayer.prototype.renderFrame = var hints = frameState.viewHints; - if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.PANNING]) { + if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) { var image_ = imageSource.getImage(frameState.extent, viewResolution); if (!goog.isNull(image_)) { var imageState = image_.getState(); diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index f51382b4d9..22cfd29744 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -199,7 +199,7 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = } } else { if (!frameState.viewHints[ol.ViewHint.ANIMATING] && - !frameState.viewHints[ol.ViewHint.PANNING]) { + !frameState.viewHints[ol.ViewHint.INTERACTING]) { tileLayerZ.removeTilesOutsideExtent(frameState.extent); } } diff --git a/src/ol/renderer/webgl/webglimagelayerrenderer.js b/src/ol/renderer/webgl/webglimagelayerrenderer.js index 5d0341f3c1..545547d198 100644 --- a/src/ol/renderer/webgl/webglimagelayerrenderer.js +++ b/src/ol/renderer/webgl/webglimagelayerrenderer.js @@ -159,7 +159,7 @@ ol.renderer.webgl.ImageLayer.prototype.renderFrame = var hints = frameState.viewHints; - if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.PANNING]) { + if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) { var image_ = imageSource.getImage(frameState.extent, viewResolution); if (!goog.isNull(image_)) { var imageState = image_.getState(); diff --git a/src/ol/view.js b/src/ol/view.js index f9303af991..61fba43f46 100644 --- a/src/ol/view.js +++ b/src/ol/view.js @@ -11,7 +11,7 @@ goog.require('ol.Object'); */ ol.ViewHint = { ANIMATING: 0, - PANNING: 1 + INTERACTING: 1 }; diff --git a/test/spec/ol/map.test.js b/test/spec/ol/map.test.js index db5ed7f546..43cda9f703 100644 --- a/test/spec/ol/map.test.js +++ b/test/spec/ol/map.test.js @@ -79,7 +79,8 @@ describe('ol.Map', function() { mouseWheelZoom: false, shiftDragZoom: false, touchPan: false, - touchRotateZoom: false + touchRotate: false, + touchZoom: false }; });