One direction pinch zoom

This commit is contained in:
Éric Lemoine
2013-03-25 18:15:00 +01:00
parent 588e0c1cdc
commit de1575e457
9 changed files with 269 additions and 137 deletions

View File

@@ -33,9 +33,12 @@ ol.array.binaryFindNearest = function(arr, target) {
/**
* @param {Array.<number>} arr Array.
* @param {number} target Target.
* @param {number} direction 0 means return the nearest, > 0
* means return the largest nearest, < 0 means return the
* smallest nearest.
* @return {number} Index.
*/
ol.array.linearFindNearest = function(arr, target) {
ol.array.linearFindNearest = function(arr, target, direction) {
var n = arr.length;
if (arr[0] <= target) {
return 0;
@@ -43,17 +46,34 @@ ol.array.linearFindNearest = function(arr, target) {
return n - 1;
} else {
var i;
for (i = 1; i < n; ++i) {
if (arr[i] == target) {
return i;
} else if (arr[i] < target) {
if (arr[i - 1] - target < target - arr[i]) {
if (direction > 0) {
for (i = 1; i < n; ++i) {
if (arr[i] < target) {
return i - 1;
} else {
}
}
} else if (direction < 0) {
for (i = 1; i < n; ++i) {
if (arr[i] <= target) {
return i;
}
}
} else {
for (i = 1; i < n; ++i) {
if (arr[i] == target) {
return i;
} else if (arr[i] < target) {
if (arr[i - 1] - target < target - arr[i]) {
return i - 1;
} else {
return i;
}
}
}
}
// We should never get here, but the compiler complains
// if it finds a path for which no number is returned.
goog.asserts.assert(false);
return n - 1;
}
};

View File

@@ -29,6 +29,12 @@ ol.interaction.TouchZoom = function() {
*/
this.lastDistance_;
/**
* @private
* @type {number}
*/
this.lastScaleDelta_ = 1;
};
goog.inherits(ol.interaction.TouchZoom, ol.interaction.Touch);
@@ -53,6 +59,9 @@ ol.interaction.TouchZoom.prototype.handleTouchMove =
scaleDelta = this.lastDistance_ / distance;
}
this.lastDistance_ = distance;
if (scaleDelta != 1.0) {
this.lastScaleDelta_ = scaleDelta;
}
var map = mapBrowserEvent.map;
var view = map.getView();
@@ -78,9 +87,12 @@ ol.interaction.TouchZoom.prototype.handleTouchEnd =
if (this.targetTouches.length < 2) {
var map = mapBrowserEvent.map;
var view = map.getView();
// take the resolution constraint into account
// Zoom to final resolution, with an animation, and provide a
// direction not to zoom out/in if user was pinching in/out.
// Direction is > 0 if pinching out, and < 0 if pinching in.
var direction = this.lastScaleDelta_ - 1;
view.zoom(map, view.getResolution(), undefined,
ol.interaction.TOUCHZOOM_ANIMATION_DURATION);
ol.interaction.TOUCHZOOM_ANIMATION_DURATION, direction);
view.setHint(ol.ViewHint.INTERACTING, -1);
return false;
} else {
@@ -97,6 +109,7 @@ ol.interaction.TouchZoom.prototype.handleTouchStart =
if (this.targetTouches.length >= 2) {
var view = mapBrowserEvent.map.getView();
this.lastDistance_ = undefined;
this.lastScaleDelta_ = 1;
view.setHint(ol.ViewHint.INTERACTING, 1);
return true;
} else {

View File

@@ -6,7 +6,7 @@ goog.require('ol.array');
/**
* @typedef {function((number|undefined), number): (number|undefined)}
* @typedef {function((number|undefined), number, number): (number|undefined)}
*/
ol.ResolutionConstraintType;
@@ -20,7 +20,7 @@ ol.ResolutionConstraintType;
ol.ResolutionConstraint.createContinuous =
function(power, maxResolution, opt_minResolution) {
var minResolution = opt_minResolution || 0;
return function(resolution, delta) {
return function(resolution, delta, direction) {
if (goog.isDef(resolution)) {
resolution /= Math.pow(power, delta);
return goog.math.clamp(resolution, minResolution, maxResolution);
@@ -37,9 +37,9 @@ ol.ResolutionConstraint.createContinuous =
*/
ol.ResolutionConstraint.createSnapToResolutions =
function(resolutions) {
return function(resolution, delta) {
return function(resolution, delta, direction) {
if (goog.isDef(resolution)) {
var z = ol.array.linearFindNearest(resolutions, resolution);
var z = ol.array.linearFindNearest(resolutions, resolution, direction);
z = goog.math.clamp(z + delta, 0, resolutions.length - 1);
return resolutions[z];
} else {
@@ -57,10 +57,18 @@ ol.ResolutionConstraint.createSnapToResolutions =
*/
ol.ResolutionConstraint.createSnapToPower =
function(power, maxResolution, opt_maxLevel) {
return function(resolution, delta) {
return function(resolution, delta, direction) {
if (goog.isDef(resolution)) {
var offset;
if (direction > 0) {
offset = 0;
} else if (direction < 0) {
offset = 1;
} else {
offset = 0.5;
}
var oldLevel = Math.floor(
Math.log(maxResolution / resolution) / Math.log(power) + 0.5);
Math.log(maxResolution / resolution) / Math.log(power) + offset);
var newLevel = Math.max(oldLevel + delta, 0);
if (goog.isDef(opt_maxLevel)) {
newLevel = Math.min(newLevel, opt_maxLevel);

View File

@@ -100,7 +100,7 @@ ol.source.ImageSource.prototype.createImage =
ol.source.ImageSource.prototype.findNearestResolution =
function(resolution) {
if (!goog.isNull(this.resolutions_)) {
var idx = ol.array.linearFindNearest(this.resolutions_, resolution);
var idx = ol.array.linearFindNearest(this.resolutions_, resolution, 0);
resolution = this.resolutions_[idx];
}
return resolution;

View File

@@ -329,7 +329,7 @@ ol.tilegrid.TileGrid.prototype.getTileSize = function(z) {
* @return {number} Z.
*/
ol.tilegrid.TileGrid.prototype.getZForResolution = function(resolution) {
return ol.array.linearFindNearest(this.resolutions_, resolution);
return ol.array.linearFindNearest(this.resolutions_, resolution, 0);
};

View File

@@ -193,7 +193,7 @@ ol.View2D.prototype.getView3D = function() {
ol.View2D.prototype.fitExtent = function(extent, size) {
this.setCenter(extent.getCenter());
var resolution = this.getResolutionForExtent(extent, size);
resolution = this.constraints_.resolution(resolution, 0);
resolution = this.constraints_.resolution(resolution, 0, 0);
this.setResolution(resolution);
};
@@ -342,10 +342,19 @@ ol.View2D.prototype.rotateWithoutConstraints =
* @param {number|undefined} resolution Resolution to go to.
* @param {ol.Coordinate=} opt_anchor Anchor coordinate.
* @param {number=} opt_duration Duration.
* @param {number=} opt_direction Zooming direction; > 0 indicates
* zooming out, in which case the constraints system will select
* the largest nearest resolution; < 0 indicates zooming in, in
* which case the constraints system will select the smallest
* nearest resolution; == 0 indicates that the zooming direction
* is unknown/not relevant, in which case the constraints system
* will select the nearest resolution. If not defined 0 is
* assumed.
*/
ol.View2D.prototype.zoom =
function(map, resolution, opt_anchor, opt_duration) {
resolution = this.constraints_.resolution(resolution, 0);
function(map, resolution, opt_anchor, opt_duration, opt_direction) {
var direction = opt_direction || 0;
resolution = this.constraints_.resolution(resolution, 0, direction);
this.zoomWithoutConstraints(map, resolution, opt_anchor, opt_duration);
};
@@ -359,7 +368,7 @@ ol.View2D.prototype.zoom =
ol.View2D.prototype.zoomByDelta =
function(map, delta, opt_anchor, opt_duration) {
var currentResolution = this.getResolution();
var resolution = this.constraints_.resolution(currentResolution, delta);
var resolution = this.constraints_.resolution(currentResolution, delta, 0);
this.zoomWithoutConstraints(map, resolution, opt_anchor, opt_duration);
};