Merge pull request #230 from fredj/touch-navigation

Touch navigation issues
This commit is contained in:
Frédéric Junod
2013-03-04 00:42:59 -08:00
13 changed files with 152 additions and 58 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -31,6 +31,7 @@ ol.interaction.Touch = function() {
/**
* @type {Array.<Object>}
* @protected
*/
this.targetTouches = [];

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}
};

View File

@@ -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) ?

View File

@@ -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();

View File

@@ -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();

View File

@@ -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);
}
}

View File

@@ -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();

View File

@@ -11,7 +11,7 @@ goog.require('ol.Object');
*/
ol.ViewHint = {
ANIMATING: 0,
PANNING: 1
INTERACTING: 1
};

View File

@@ -79,7 +79,8 @@ describe('ol.Map', function() {
mouseWheelZoom: false,
shiftDragZoom: false,
touchPan: false,
touchRotateZoom: false
touchRotate: false,
touchZoom: false
};
});