diff --git a/examples/min-zoom.html b/examples/min-zoom.html new file mode 100644 index 0000000000..6f03f6d311 --- /dev/null +++ b/examples/min-zoom.html @@ -0,0 +1,12 @@ +--- +layout: example.html +title: View Min-Zoom +shortdesc: Demonstrates how the view's minimum zoom level can be changed. +docs: > + The minZoom option for a view limits how far out you can + zoom. This property can be updated by calling view.setMinZoom(newMinZoom). + In this example, the minimum zoom level is set so that you only see one + world at a time. Resize your browser window to change the threshold. +tags: "min, zoom" +--- +
diff --git a/examples/min-zoom.js b/examples/min-zoom.js new file mode 100644 index 0000000000..af35ff4405 --- /dev/null +++ b/examples/min-zoom.js @@ -0,0 +1,36 @@ +goog.require('ol.Map'); +goog.require('ol.View'); +goog.require('ol.layer.Tile'); +goog.require('ol.source.OSM'); + +var viewport = document.getElementById('map'); + +function getMinZoom() { + var width = viewport.clientWidth; + return Math.ceil(Math.LOG2E * Math.log(width / 256)); +} + +var initialZoom = getMinZoom(); + +var view = new ol.View({ + center: [0, 0], + minZoom: initialZoom, + zoom: initialZoom +}); + +var map = new ol.Map({ + layers: [ + new ol.layer.Tile({ + source: new ol.source.OSM() + }) + ], + target: 'map', + view: view +}); + +window.addEventListener('resize', function() { + var minZoom = getMinZoom(); + if (minZoom !== view.getMinZoom()) { + view.setMinZoom(minZoom); + } +}); diff --git a/src/ol/view.js b/src/ol/view.js index 1327c4691e..333efca9f4 100644 --- a/src/ol/view.js +++ b/src/ol/view.js @@ -16,6 +16,7 @@ goog.require('ol.extent'); goog.require('ol.geom.GeometryType'); goog.require('ol.geom.Polygon'); goog.require('ol.geom.SimpleGeometry'); +goog.require('ol.obj'); goog.require('ol.proj'); goog.require('ol.proj.Units'); @@ -79,7 +80,8 @@ goog.require('ol.proj.Units'); */ ol.View = function(opt_options) { ol.Object.call(this); - var options = opt_options || {}; + + var options = ol.obj.assign({}, opt_options); /** * @private @@ -101,13 +103,6 @@ ol.View = function(opt_options) { this.updateAnimations_ = this.updateAnimations_.bind(this); - /** - * @type {Object.} - */ - var properties = {}; - properties[ol.ViewProperty.CENTER] = options.center !== undefined ? - options.center : null; - /** * @private * @const @@ -115,6 +110,24 @@ ol.View = function(opt_options) { */ this.projection_ = ol.proj.createProjection(options.projection, 'EPSG:3857'); + this.applyOptions_(options); +}; +ol.inherits(ol.View, ol.Object); + + +/** + * Set up the view with the given options. + * @param {olx.ViewOptions} options View options. + */ +ol.View.prototype.applyOptions_ = function(options) { + + /** + * @type {Object.} + */ + var properties = {}; + properties[ol.ViewProperty.CENTER] = options.center !== undefined ? + options.center : null; + var resolutionConstraintInfo = ol.View.createResolutionConstraint_( options); @@ -168,8 +181,41 @@ ol.View = function(opt_options) { properties[ol.ViewProperty.ROTATION] = options.rotation !== undefined ? options.rotation : 0; this.setProperties(properties); + + /** + * @private + * @type {olx.ViewOptions} + */ + this.options_ = options; + +}; + +/** + * Get an updated version of the view options used to construct the view. The + * current resolution (or zoom), center, and rotation are applied to any stored + * options. The provided options can be uesd to apply new min/max zoom or + * resolution limits. + * @param {olx.ViewOptions} newOptions New options to be applied. + * @return {olx.ViewOptions} New options updated with the current view state. + */ +ol.View.prototype.getUpdatedOptions_ = function(newOptions) { + var options = ol.obj.assign({}, this.options_); + + // preserve resolution (or zoom) + if (options.resolution !== undefined) { + options.resolution = this.getResolution(); + } else { + options.zoom = this.getZoom(); + } + + // preserve center + options.center = this.getCenter(); + + // preserve rotation + options.rotation = this.getRotation(); + + return ol.obj.assign({}, options, newOptions); }; -ol.inherits(ol.View, ol.Object); /** @@ -540,6 +586,16 @@ ol.View.prototype.getMaxZoom = function() { }; +/** + * Set a new maximum zoom level for the view. + * @param {number} zoom The maximum zoom level. + * @api + */ +ol.View.prototype.setMaxZoom = function(zoom) { + this.applyOptions_(this.getUpdatedOptions_({maxZoom: zoom})); +}; + + /** * Get the minimum zoom level for the view. * @return {number} The minimum zoom level. @@ -550,6 +606,16 @@ ol.View.prototype.getMinZoom = function() { }; +/** + * Set a new minimum zoom level for the view. + * @param {number} zoom The minimum zoom level. + * @api + */ +ol.View.prototype.setMinZoom = function(zoom) { + this.applyOptions_(this.getUpdatedOptions_({minZoom: zoom})); +}; + + /** * Get the view projection. * @return {ol.proj.Projection} The projection of the view. diff --git a/test/spec/ol/view.test.js b/test/spec/ol/view.test.js index d12505d538..cf06ec2fea 100644 --- a/test/spec/ol/view.test.js +++ b/test/spec/ol/view.test.js @@ -330,6 +330,72 @@ describe('ol.View', function() { }); + describe('#getUpdatedOptions_()', function() { + + it('applies minZoom to constructor options', function() { + var view = new ol.View({ + center: [0, 0], + minZoom: 2, + zoom: 10 + }); + var options = view.getUpdatedOptions_({minZoom: 3}); + + expect(options.center).to.eql([0, 0]); + expect(options.minZoom).to.eql(3); + expect(options.zoom).to.eql(10); + }); + + it('applies the current zoom', function() { + var view = new ol.View({ + center: [0, 0], + zoom: 10 + }); + view.setZoom(8); + var options = view.getUpdatedOptions_(); + + expect(options.center).to.eql([0, 0]); + expect(options.zoom).to.eql(8); + }); + + it('applies the current resolution if resolution was originally supplied', function() { + var view = new ol.View({ + center: [0, 0], + resolution: 1000 + }); + view.setResolution(500); + var options = view.getUpdatedOptions_(); + + expect(options.center).to.eql([0, 0]); + expect(options.resolution).to.eql(500); + }); + + it('applies the current center', function() { + var view = new ol.View({ + center: [0, 0], + zoom: 10 + }); + view.setCenter([1, 2]); + var options = view.getUpdatedOptions_(); + + expect(options.center).to.eql([1, 2]); + expect(options.zoom).to.eql(10); + }); + + it('applies the current rotation', function() { + var view = new ol.View({ + center: [0, 0], + zoom: 10 + }); + view.setRotation(Math.PI / 6); + var options = view.getUpdatedOptions_(); + + expect(options.center).to.eql([0, 0]); + expect(options.zoom).to.eql(10); + expect(options.rotation).to.eql(Math.PI / 6); + }); + + }); + describe('#animate()', function() { var originalRequestAnimationFrame = window.requestAnimationFrame;