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;