From 3793f33acfd913eabff8c5fd5055c163920a52fd Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Thu, 15 May 2014 17:27:53 -0600 Subject: [PATCH] Handle minZoom in getZoom and setZoom --- examples/zoom-constrained.html | 52 +++++++++++++++++++++++++++ examples/zoom-constrained.js | 23 ++++++++++++ src/ol/ol.js | 8 +++++ src/ol/view2d.js | 53 ++++++++++++++++------------ test/spec/ol/view2d.test.js | 64 ++++++++++++++++++++++++++++++++++ 5 files changed, 177 insertions(+), 23 deletions(-) create mode 100644 examples/zoom-constrained.html create mode 100644 examples/zoom-constrained.js diff --git a/examples/zoom-constrained.html b/examples/zoom-constrained.html new file mode 100644 index 0000000000..aea4b44a71 --- /dev/null +++ b/examples/zoom-constrained.html @@ -0,0 +1,52 @@ + + + + + + + + + + + Zoom Constrained Example + + + + + +
+ +
+
+
+
+
+ +
+ +
+

Zoom constrained example

+

Example of a zoom constrained view.

+
+

This map has a view that is constrained between zoom levels 9 and 13. This is done using the minZoom and maxZoom view options.

+

See the zoom-constrained.js source for details.

+
+
bing, zoom, minZoom, maxZoom
+
+ +
+ +
+ + + + + + + diff --git a/examples/zoom-constrained.js b/examples/zoom-constrained.js new file mode 100644 index 0000000000..a8ad02ddcc --- /dev/null +++ b/examples/zoom-constrained.js @@ -0,0 +1,23 @@ +goog.require('ol.Map'); +goog.require('ol.View2D'); +goog.require('ol.layer.Tile'); +goog.require('ol.source.BingMaps'); + + +var map = new ol.Map({ + target: 'map', + layers: [ + new ol.layer.Tile({ + source: new ol.source.BingMaps({ + key: 'Ak-dzM4wZjSqTlzveKz5u0d4IQ4bRzVI309GxmkgSVr1ewS6iPSrOvOKhA-CJlm3', + imagerySet: 'Aerial' + }) + }) + ], + view: new ol.View2D({ + center: [-13553864, 5918250], + zoom: 11, + minZoom: 9, + maxZoom: 13 + }) +}); diff --git a/src/ol/ol.js b/src/ol/ol.js index 68ab072af0..56c0874dc6 100644 --- a/src/ol/ol.js +++ b/src/ol/ol.js @@ -16,11 +16,19 @@ ol.BUFFER_REPLACE_UNUSED_ENTRIES_WITH_NANS = goog.DEBUG; /** + * TODO: rename this to something having to do with tile grids + * see https://github.com/openlayers/ol3/issues/2076 * @define {number} Default maximum zoom for default tile grids. */ ol.DEFAULT_MAX_ZOOM = 42; +/** + * @define {number} Default min zoom level for the map view. Default is `0`. + */ +ol.DEFAULT_MIN_ZOOM = 0; + + /** * @define {number} Default high water mark. */ diff --git a/src/ol/view2d.js b/src/ol/view2d.js index 76a7d4aa7a..a7ceb527c5 100644 --- a/src/ol/view2d.js +++ b/src/ol/view2d.js @@ -116,6 +116,12 @@ ol.View2D = function(opt_options) { */ this.minResolution_ = resolutionConstraintInfo.minResolution; + /** + * @private + * @type {number} + */ + this.minZoom_ = resolutionConstraintInfo.minZoom; + var centerConstraint = ol.View2D.createCenterConstraint_(options); var resolutionConstraint = resolutionConstraintInfo.constraint; var rotationConstraint = ol.View2D.createRotationConstraint_(options); @@ -131,7 +137,7 @@ ol.View2D = function(opt_options) { values[ol.View2DProperty.RESOLUTION] = options.resolution; } else if (goog.isDef(options.zoom)) { values[ol.View2DProperty.RESOLUTION] = this.constrainResolution( - this.maxResolution_, options.zoom); + this.maxResolution_, options.zoom - this.minZoom_); } values[ol.View2DProperty.ROTATION] = goog.isDef(options.rotation) ? options.rotation : 0; @@ -396,7 +402,7 @@ ol.View2D.prototype.getView3D = function() { * @todo api */ ol.View2D.prototype.getZoom = function() { - var zoom; + var offset; var resolution = this.getResolution(); if (goog.isDef(resolution)) { @@ -404,14 +410,14 @@ ol.View2D.prototype.getZoom = function() { do { res = this.constrainResolution(this.maxResolution_, z); if (res == resolution) { - zoom = z; + offset = z; break; } ++z; } while (res > this.minResolution_); } - return zoom; + return goog.isDef(offset) ? this.minZoom_ + offset : offset; }; @@ -621,7 +627,8 @@ goog.exportProperty( * @todo api */ ol.View2D.prototype.setZoom = function(zoom) { - var resolution = this.constrainResolution(this.maxResolution_, zoom, 0); + var resolution = this.constrainResolution( + this.maxResolution_, zoom - this.minZoom_, 0); this.setResolution(resolution); }; @@ -650,6 +657,21 @@ ol.View2D.createResolutionConstraint_ = function(options) { var resolutionConstraint; var maxResolution; var minResolution; + + // TODO: move these to be ol constants + // see https://github.com/openlayers/ol3/issues/2076 + var defaultMaxZoom = 28; + var defaultZoomFactor = 2; + + var minZoom = goog.isDef(options.minZoom) ? + options.minZoom : ol.DEFAULT_MIN_ZOOM; + + var maxZoom = goog.isDef(options.maxZoom) ? + options.maxZoom : defaultMaxZoom; + + var zoomFactor = goog.isDef(options.zoomFactor) ? + options.zoomFactor : defaultZoomFactor; + if (goog.isDef(options.resolutions)) { var resolutions = options.resolutions; maxResolution = resolutions[0]; @@ -657,12 +679,6 @@ ol.View2D.createResolutionConstraint_ = function(options) { resolutionConstraint = ol.ResolutionConstraint.createSnapToResolutions( resolutions); } else { - // TODO: move these to be ol constants - // see https://github.com/openlayers/ol3/issues/2076 - var defaultMaxZoom = 28; - var defaultMinZoom = 0; - var defaultZoomFactor = 2; - // calculate the default min and max resolution var projection = options.projection; var extent = ol.proj.createProjection(projection, 'EPSG:3857').getExtent(); @@ -673,19 +689,10 @@ ol.View2D.createResolutionConstraint_ = function(options) { Math.max(ol.extent.getWidth(extent), ol.extent.getHeight(extent)); var defaultMaxResolution = size / ol.DEFAULT_TILE_SIZE / Math.pow( - defaultZoomFactor, defaultMinZoom); + defaultZoomFactor, ol.DEFAULT_MIN_ZOOM); var defaultMinResolution = defaultMaxResolution / Math.pow( - defaultZoomFactor, defaultMaxZoom - defaultMinZoom); - - var minZoom = goog.isDef(options.minZoom) ? - options.minZoom : defaultMinZoom; - - var maxZoom = goog.isDef(options.maxZoom) ? - options.maxZoom : defaultMaxZoom; - - var zoomFactor = goog.isDef(options.zoomFactor) ? - options.zoomFactor : defaultZoomFactor; + defaultZoomFactor, defaultMaxZoom - ol.DEFAULT_MIN_ZOOM); // user provided maxResolution takes precedence maxResolution = options.maxResolution; @@ -718,7 +725,7 @@ ol.View2D.createResolutionConstraint_ = function(options) { zoomFactor, maxResolution, maxZoom - minZoom); } return {constraint: resolutionConstraint, maxResolution: maxResolution, - minResolution: minResolution}; + minResolution: minResolution, minZoom: minZoom}; }; diff --git a/test/spec/ol/view2d.test.js b/test/spec/ol/view2d.test.js index 604a98527a..b9605b8a37 100644 --- a/test/spec/ol/view2d.test.js +++ b/test/spec/ol/view2d.test.js @@ -282,6 +282,70 @@ describe('ol.View2D', function() { }); }); + describe('#getZoom() - constrained', function() { + it('returns correct zoom levels', function() { + var view = new ol.View2D({ + minZoom: 10, + maxZoom: 20 + }); + + view.setZoom(5); + expect(view.getZoom()).to.be(10); + + view.setZoom(10); + expect(view.getZoom()).to.be(10); + + view.setZoom(15); + expect(view.getZoom()).to.be(15); + + view.setZoom(20); + expect(view.getZoom()).to.be(20); + + view.setZoom(25); + expect(view.getZoom()).to.be(20); + }); + }); + + describe('#getZoom() - custom ol.DEFAULT_MIN_ZOOM', function() { + var defaultMinZoom = ol.DEFAULT_MIN_ZOOM; + + afterEach(function() { + ol.DEFAULT_MIN_ZOOM = defaultMinZoom; + }); + + it('respects custom ol.DEFAULT_MIN_ZOOM', function() { + ol.DEFAULT_MIN_ZOOM = 2; + + var view = new ol.View2D(); + + view.setZoom(1); + expect(view.getZoom()).to.be(2); + + view.setZoom(2); + expect(view.getZoom()).to.be(2); + + view.setZoom(3); + expect(view.getZoom()).to.be(3); + }); + }); + + describe('#getZoom() - overspecified', function() { + + it('gives maxResolution precedence over minZoom', function() { + + var view = new ol.View2D({ + maxResolution: 100, + minZoom: 2 // this should get ignored + }); + + view.setResolution(100); + expect(view.getZoom()).to.be(0); + + view.setZoom(0); + expect(view.getResolution()).to.be(100); + }); + }); + describe('fitGeometry', function() { var view; beforeEach(function() {