Support fractional zoom levels in ol.View#getZoom and #setZoom

This commit is contained in:
Andreas Hocevar
2016-08-02 22:52:57 +02:00
parent 3d57ea45cb
commit 98fbfe4b67
3 changed files with 67 additions and 29 deletions
+8 -9
View File
@@ -21,7 +21,13 @@ ol.ResolutionConstraint.createSnapToResolutions = function(resolutions) {
var z = var z =
ol.array.linearFindNearest(resolutions, resolution, direction); ol.array.linearFindNearest(resolutions, resolution, direction);
z = ol.math.clamp(z + delta, 0, resolutions.length - 1); z = ol.math.clamp(z + delta, 0, resolutions.length - 1);
return resolutions[z]; var index = Math.floor(z);
if (z != index && index < resolutions.length - 1) {
var power = resolutions[index] / resolutions[index + 1];
return resolutions[index] / Math.pow(power, z - index);
} else {
return resolutions[index];
}
} else { } else {
return undefined; return undefined;
} }
@@ -45,14 +51,7 @@ ol.ResolutionConstraint.createSnapToPower = function(power, maxResolution, opt_m
*/ */
function(resolution, delta, direction) { function(resolution, delta, direction) {
if (resolution !== undefined) { if (resolution !== undefined) {
var offset; var offset = -direction / 2 + 0.5;
if (direction > 0) {
offset = 0;
} else if (direction < 0) {
offset = 1;
} else {
offset = 0.5;
}
var oldLevel = Math.floor( var oldLevel = Math.floor(
Math.log(maxResolution / resolution) / Math.log(power) + offset); Math.log(maxResolution / resolution) / Math.log(power) + offset);
var newLevel = Math.max(oldLevel + delta, 0); var newLevel = Math.max(oldLevel + delta, 0);
+27 -16
View File
@@ -134,6 +134,12 @@ ol.View = function(opt_options) {
*/ */
this.minResolution_ = resolutionConstraintInfo.minResolution; this.minResolution_ = resolutionConstraintInfo.minResolution;
/**
* @private
* @type {number}
*/
this.zoomFactor_ = resolutionConstraintInfo.zoomFactor;
/** /**
* @private * @private
* @type {Array.<number>|undefined} * @type {Array.<number>|undefined}
@@ -453,27 +459,32 @@ ol.View.prototype.getState = function() {
/** /**
* Get the current zoom level. Return undefined if the current * Get the current zoom level. Return undefined if the current
* resolution is undefined or not a "constrained resolution". * resolution is undefined or not within the "resolution constraints".
* @return {number|undefined} Zoom. * @return {number|undefined} Zoom.
* @api stable * @api stable
*/ */
ol.View.prototype.getZoom = function() { ol.View.prototype.getZoom = function() {
var offset; var zoom;
var resolution = this.getResolution(); var resolution = this.getResolution();
if (resolution !== undefined &&
if (resolution !== undefined) { resolution >= this.minResolution_ && resolution <= this.maxResolution_) {
var res, z = 0; var offset = this.minZoom_ || 0;
do { var max, zoomFactor;
res = this.constrainResolution(this.maxResolution_, z); if (this.resolutions_) {
if (res == resolution) { var nearest = ol.array.linearFindNearest(this.resolutions_, resolution, 1);
offset = z; offset += nearest;
break; if (nearest == this.resolutions_.length - 1) {
return offset;
} }
++z; max = this.resolutions_[nearest];
} while (res > this.minResolution_); zoomFactor = max / this.resolutions_[nearest + 1];
} else {
max = this.maxResolution_;
zoomFactor = this.zoomFactor_;
}
zoom = offset + Math.log(max / resolution) / Math.log(zoomFactor);
} }
return zoom;
return offset !== undefined ? this.minZoom_ + offset : offset;
}; };
@@ -689,7 +700,7 @@ ol.View.createCenterConstraint_ = function(options) {
* @private * @private
* @param {olx.ViewOptions} options View options. * @param {olx.ViewOptions} options View options.
* @return {{constraint: ol.ResolutionConstraintType, maxResolution: number, * @return {{constraint: ol.ResolutionConstraintType, maxResolution: number,
* minResolution: number}} The constraint. * minResolution: number, zoomFactor: number}} The constraint.
*/ */
ol.View.createResolutionConstraint_ = function(options) { ol.View.createResolutionConstraint_ = function(options) {
var resolutionConstraint; var resolutionConstraint;
@@ -763,7 +774,7 @@ ol.View.createResolutionConstraint_ = function(options) {
zoomFactor, maxResolution, maxZoom - minZoom); zoomFactor, maxResolution, maxZoom - minZoom);
} }
return {constraint: resolutionConstraint, maxResolution: maxResolution, return {constraint: resolutionConstraint, maxResolution: maxResolution,
minResolution: minResolution, minZoom: minZoom}; minResolution: minResolution, minZoom: minZoom, zoomFactor: zoomFactor};
}; };
+32 -4
View File
@@ -323,17 +323,20 @@ describe('ol.View', function() {
view.setResolution(undefined); view.setResolution(undefined);
expect(view.getZoom()).to.be(undefined); expect(view.getZoom()).to.be(undefined);
view.setResolution(511); view.setResolution(513);
expect(view.getZoom()).to.be(undefined); expect(view.getZoom()).to.be(undefined);
view.setResolution(512); view.setResolution(512);
expect(view.getZoom()).to.be(0); expect(view.getZoom()).to.be(0);
view.setResolution(64); view.setResolution(100);
expect(view.getZoom()).to.be(3); expect(view.getZoom()).to.roughlyEqual(2.35614, 1e-5);
view.setResolution(65); view.setResolution(65);
expect(view.getZoom()).to.be(undefined); expect(view.getZoom()).to.roughlyEqual(2.97763, 1e-5);
view.setResolution(64);
expect(view.getZoom()).to.be(3);
view.setResolution(16); view.setResolution(16);
expect(view.getZoom()).to.be(5); expect(view.getZoom()).to.be(5);
@@ -341,6 +344,28 @@ describe('ol.View', function() {
view.setResolution(15); view.setResolution(15);
expect(view.getZoom()).to.be(undefined); expect(view.getZoom()).to.be(undefined);
}); });
it('works for resolution arrays with variable zoom factors', function() {
var view = new ol.View({
resolutions: [10, 5, 2, 1]
});
view.setZoom(1);
expect(view.getZoom()).to.be(1);
view.setZoom(1.3);
expect(view.getZoom()).to.be(1.3);
view.setZoom(2);
expect(view.getZoom()).to.be(2);
view.setZoom(2.7);
expect(view.getZoom()).to.be(2.7);
view.setZoom(3);
expect(view.getZoom()).to.be(3);
});
}); });
describe('#getZoom() - constrained', function() { describe('#getZoom() - constrained', function() {
@@ -359,6 +384,9 @@ describe('ol.View', function() {
view.setZoom(15); view.setZoom(15);
expect(view.getZoom()).to.be(15); expect(view.getZoom()).to.be(15);
view.setZoom(15.3);
expect(view.getZoom()).to.be(15.3);
view.setZoom(20); view.setZoom(20);
expect(view.getZoom()).to.be(20); expect(view.getZoom()).to.be(20);