diff --git a/examples/layer-zoom-limits.html b/examples/layer-zoom-limits.html
new file mode 100644
index 0000000000..9727e34383
--- /dev/null
+++ b/examples/layer-zoom-limits.html
@@ -0,0 +1,13 @@
+---
+layout: example.html
+title: Layer Zoom Limits
+shortdesc: Using minZoom and maxZoom to control layer visibility.
+docs: >
+ Layers support `minZoom` and `maxZoom` options for controlling visibility based on the view's zoom level.
+ If min or max zoom are set, the layer will only be visible at zoom levels greater than the `minZoom` and
+ less than or equal to the `maxZoom`. After construction, the layer's `setMinZoom` and `setMaxZoom` can
+ be used to set limits. This example shows an OSM layer at zoom levels 14 and lower and a USGS layer at
+ zoom levels higher than 14.
+tags: "minZoom, maxZoom, layer"
+---
+
diff --git a/examples/layer-zoom-limits.js b/examples/layer-zoom-limits.js
new file mode 100644
index 0000000000..0fa5ab4ada
--- /dev/null
+++ b/examples/layer-zoom-limits.js
@@ -0,0 +1,33 @@
+import Map from '../src/ol/Map.js';
+import View from '../src/ol/View.js';
+import TileLayer from '../src/ol/layer/Tile.js';
+import OSM from '../src/ol/source/OSM.js';
+import XYZ from '../src/ol/source/XYZ.js';
+import {transformExtent, fromLonLat} from '../src/ol/proj.js';
+
+const mapExtent = [-112.261791, 35.983744, -112.113981, 36.132062];
+
+const map = new Map({
+ target: 'map',
+ layers: [
+ new TileLayer({
+ maxZoom: 14, // visible at zoom levels 14 and below
+ source: new OSM()
+ }),
+ new TileLayer({
+ minZoom: 14, // visible at zoom levels above 14
+ source: new XYZ({
+ attributions: 'Tiles © USGS, rendered with ' +
+ 'MapTiler',
+ url: 'https://tileserver.maptiler.com/grandcanyon/{z}/{x}/{y}.png'
+ })
+ })
+ ],
+ view: new View({
+ center: fromLonLat([-112.18688965, 36.057944835]),
+ zoom: 15,
+ maxZoom: 18,
+ extent: transformExtent(mapExtent, 'EPSG:4326', 'EPSG:3857'),
+ constrainOnlyCenter: true
+ })
+});
diff --git a/src/ol/control/Attribution.js b/src/ol/control/Attribution.js
index e69ff13892..bb3ffcc805 100644
--- a/src/ol/control/Attribution.js
+++ b/src/ol/control/Attribution.js
@@ -7,7 +7,7 @@ import {CLASS_CONTROL, CLASS_UNSELECTABLE, CLASS_COLLAPSED} from '../css.js';
import {removeChildren, replaceNode} from '../dom.js';
import {listen} from '../events.js';
import EventType from '../events/EventType.js';
-import {visibleAtResolution} from '../layer/Layer.js';
+import {inView} from '../layer/Layer.js';
/**
@@ -170,10 +170,9 @@ class Attribution extends Control {
const visibleAttributions = [];
const layerStatesArray = frameState.layerStatesArray;
- const resolution = frameState.viewState.resolution;
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
const layerState = layerStatesArray[i];
- if (!visibleAtResolution(layerState, resolution)) {
+ if (!inView(layerState, frameState.viewState)) {
continue;
}
diff --git a/src/ol/layer/Base.js b/src/ol/layer/Base.js
index 60c5cab6c9..2be76892d7 100644
--- a/src/ol/layer/Base.js
+++ b/src/ol/layer/Base.js
@@ -23,6 +23,10 @@ import {assign} from '../obj.js';
* visible.
* @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will
* be visible.
+ * @property {number} [minZoom] The minimum view zoom level (exclusive) above which this layer will be
+ * visible.
+ * @property {number} [maxZoom] The maximum view zoom level (inclusive) at which this layer will
+ * be visible.
*/
@@ -57,6 +61,10 @@ class BaseLayer extends BaseObject {
options.maxResolution !== undefined ? options.maxResolution : Infinity;
properties[LayerProperty.MIN_RESOLUTION] =
options.minResolution !== undefined ? options.minResolution : 0;
+ properties[LayerProperty.MIN_ZOOM] =
+ options.minZoom !== undefined ? options.minZoom : -Infinity;
+ properties[LayerProperty.MAX_ZOOM] =
+ options.maxZoom !== undefined ? options.maxZoom : Infinity;
/**
* @type {string}
@@ -103,6 +111,8 @@ class BaseLayer extends BaseObject {
state.zIndex = this.getZIndex() || (state.managed === false ? Infinity : 0);
state.maxResolution = this.getMaxResolution();
state.minResolution = Math.max(this.getMinResolution(), 0);
+ state.minZoom = this.getMinZoom();
+ state.maxZoom = this.getMaxZoom();
this.state_ = state;
return state;
@@ -161,6 +171,26 @@ class BaseLayer extends BaseObject {
return /** @type {number} */ (this.get(LayerProperty.MIN_RESOLUTION));
}
+ /**
+ * Return the minimum zoom level of the layer.
+ * @return {number} The minimum zoom level of the layer.
+ * @observable
+ * @api
+ */
+ getMinZoom() {
+ return /** @type {number} */ (this.get(LayerProperty.MIN_ZOOM));
+ }
+
+ /**
+ * Return the maximum zoom level of the layer.
+ * @return {number} The maximum zoom level of the layer.
+ * @observable
+ * @api
+ */
+ getMaxZoom() {
+ return /** @type {number} */ (this.get(LayerProperty.MAX_ZOOM));
+ }
+
/**
* Return the opacity of the layer (between 0 and 1).
* @return {number} The opacity of the layer.
@@ -231,6 +261,30 @@ class BaseLayer extends BaseObject {
this.set(LayerProperty.MIN_RESOLUTION, minResolution);
}
+ /**
+ * Set the maximum zoom (exclusive) at which the layer is visible.
+ * Note that the zoom levels for layer visibility are based on the
+ * view zoom level, which may be different from a tile source zoom level.
+ * @param {number} maxZoom The maximum zoom of the layer.
+ * @observable
+ * @api
+ */
+ setMaxZoom(maxZoom) {
+ this.set(LayerProperty.MAX_ZOOM, maxZoom);
+ }
+
+ /**
+ * Set the minimum zoom (inclusive) at which the layer is visible.
+ * Note that the zoom levels for layer visibility are based on the
+ * view zoom level, which may be different from a tile source zoom level.
+ * @param {number} minZoom The minimum zoom of the layer.
+ * @observable
+ * @api
+ */
+ setMinZoom(minZoom) {
+ this.set(LayerProperty.MIN_ZOOM, minZoom);
+ }
+
/**
* Set the opacity of the layer, allowed values range from 0 to 1.
* @param {number} opacity The opacity of the layer.
diff --git a/src/ol/layer/Group.js b/src/ol/layer/Group.js
index 7878961535..26a966798b 100644
--- a/src/ol/layer/Group.js
+++ b/src/ol/layer/Group.js
@@ -29,6 +29,10 @@ import SourceState from '../source/State.js';
* visible.
* @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will
* be visible.
+ * @property {number} [minZoom] The minimum view zoom level (exclusive) above which this layer will be
+ * visible.
+ * @property {number} [maxZoom] The maximum view zoom level (inclusive) at which this layer will
+ * be visible.
* @property {Array|import("../Collection.js").default} [layers] Child layers.
*/
@@ -215,6 +219,10 @@ class LayerGroup extends BaseLayer {
layerState.maxResolution, ownLayerState.maxResolution);
layerState.minResolution = Math.max(
layerState.minResolution, ownLayerState.minResolution);
+ layerState.minZoom = Math.max(
+ layerState.minZoom, ownLayerState.minZoom);
+ layerState.maxZoom = Math.min(
+ layerState.maxZoom, ownLayerState.maxZoom);
if (ownLayerState.extent !== undefined) {
if (layerState.extent !== undefined) {
layerState.extent = getIntersection(layerState.extent, ownLayerState.extent);
diff --git a/src/ol/layer/Layer.js b/src/ol/layer/Layer.js
index b286a99ad4..b9541a4ab7 100644
--- a/src/ol/layer/Layer.js
+++ b/src/ol/layer/Layer.js
@@ -50,6 +50,8 @@ import SourceState from '../source/State.js';
* @property {number} zIndex
* @property {number} maxResolution
* @property {number} minResolution
+ * @property {number} minZoom
+ * @property {number} maxZoom
*/
/**
@@ -277,17 +279,22 @@ class Layer extends BaseLayer {
/**
- * Return `true` if the layer is visible, and if the passed resolution is
- * between the layer's minResolution and maxResolution. The comparison is
- * inclusive for `minResolution` and exclusive for `maxResolution`.
+ * Return `true` if the layer is visible and if the provided view state
+ * has resolution and zoom levels that are in range of the layer's min/max.
* @param {State} layerState Layer state.
- * @param {number} resolution Resolution.
- * @return {boolean} The layer is visible at the given resolution.
+ * @param {import("../View.js").State} viewState View state.
+ * @return {boolean} The layer is visible at the given view state.
*/
-export function visibleAtResolution(layerState, resolution) {
- return layerState.visible && resolution >= layerState.minResolution &&
- resolution < layerState.maxResolution;
+export function inView(layerState, viewState) {
+ if (!layerState.visible) {
+ return false;
+ }
+ const resolution = viewState.resolution;
+ if (resolution < layerState.minResolution || resolution >= layerState.maxResolution) {
+ return false;
+ }
+ const zoom = viewState.zoom;
+ return zoom > layerState.minZoom && zoom <= layerState.maxZoom;
}
-
export default Layer;
diff --git a/src/ol/layer/Property.js b/src/ol/layer/Property.js
index a8d8fe3ad2..f49bdce9e8 100644
--- a/src/ol/layer/Property.js
+++ b/src/ol/layer/Property.js
@@ -12,5 +12,7 @@ export default {
Z_INDEX: 'zIndex',
MAX_RESOLUTION: 'maxResolution',
MIN_RESOLUTION: 'minResolution',
+ MAX_ZOOM: 'maxZoom',
+ MIN_ZOOM: 'minZoom',
SOURCE: 'source'
};
diff --git a/src/ol/renderer/Composite.js b/src/ol/renderer/Composite.js
index 16c2f0331f..2b44ff1981 100644
--- a/src/ol/renderer/Composite.js
+++ b/src/ol/renderer/Composite.js
@@ -2,7 +2,7 @@
* @module ol/renderer/Composite
*/
import {CLASS_UNSELECTABLE} from '../css.js';
-import {visibleAtResolution} from '../layer/Layer.js';
+import {inView} from '../layer/Layer.js';
import RenderEvent from '../render/Event.js';
import RenderEventType from '../render/EventType.js';
import MapRenderer from './Map.js';
@@ -95,7 +95,7 @@ class CompositeMapRenderer extends MapRenderer {
const layerStatesArray = frameState.layerStatesArray.sort(function(a, b) {
return a.zIndex - b.zIndex;
});
- const viewResolution = frameState.viewState.resolution;
+ const viewState = frameState.viewState;
this.children_.length = 0;
let hasOverlay = false;
@@ -104,7 +104,7 @@ class CompositeMapRenderer extends MapRenderer {
const layerState = layerStatesArray[i];
hasOverlay = hasOverlay || layerState.hasOverlay;
frameState.layerIndex = i;
- if (!visibleAtResolution(layerState, viewResolution) ||
+ if (!inView(layerState, viewState) ||
(layerState.sourceState != SourceState.READY && layerState.sourceState != SourceState.UNDEFINED)) {
continue;
}
@@ -142,7 +142,6 @@ class CompositeMapRenderer extends MapRenderer {
*/
forEachLayerAtPixel(pixel, frameState, hitTolerance, callback, layerFilter) {
const viewState = frameState.viewState;
- const viewResolution = viewState.resolution;
const layerStates = frameState.layerStatesArray;
const numLayers = layerStates.length;
@@ -150,7 +149,7 @@ class CompositeMapRenderer extends MapRenderer {
for (let i = numLayers - 1; i >= 0; --i) {
const layerState = layerStates[i];
const layer = layerState.layer;
- if (layer.hasRenderer() && visibleAtResolution(layerState, viewResolution) && layerFilter(layer)) {
+ if (layer.hasRenderer() && inView(layerState, viewState) && layerFilter(layer)) {
const layerRenderer = layer.getRenderer();
const data = layerRenderer.getDataAtPixel(pixel, frameState, hitTolerance);
if (data) {
diff --git a/src/ol/renderer/Map.js b/src/ol/renderer/Map.js
index 8cde8fc7f2..c8efb1bb72 100644
--- a/src/ol/renderer/Map.js
+++ b/src/ol/renderer/Map.js
@@ -5,7 +5,7 @@ import {abstract, getUid} from '../util.js';
import Disposable from '../Disposable.js';
import {getWidth} from '../extent.js';
import {TRUE} from '../functions.js';
-import {visibleAtResolution} from '../layer/Layer.js';
+import {inView} from '../layer/Layer.js';
import {shared as iconImageCache} from '../style/IconImageCache.js';
import {compose as composeTransform, makeInverse} from '../transform.js';
import {renderDeclutterItems} from '../render.js';
@@ -87,7 +87,6 @@ class MapRenderer extends Disposable {
) {
let result;
const viewState = frameState.viewState;
- const viewResolution = viewState.resolution;
/**
* @param {boolean} managed Managed layer.
@@ -126,7 +125,7 @@ class MapRenderer extends Disposable {
for (i = numLayers - 1; i >= 0; --i) {
const layerState = layerStates[i];
const layer = /** @type {import("../layer/Layer.js").default} */ (layerState.layer);
- if (layer.hasRenderer() && visibleAtResolution(layerState, viewResolution) && layerFilter.call(thisArg2, layer)) {
+ if (layer.hasRenderer() && inView(layerState, viewState) && layerFilter.call(thisArg2, layer)) {
const layerRenderer = layer.getRenderer();
const source = layer.getSource();
if (layerRenderer && source) {
diff --git a/test/spec/ol/layer/group.test.js b/test/spec/ol/layer/group.test.js
index f7737b09a1..6a7292d928 100644
--- a/test/spec/ol/layer/group.test.js
+++ b/test/spec/ol/layer/group.test.js
@@ -44,7 +44,9 @@ describe('ol.layer.Group', function() {
extent: undefined,
zIndex: 0,
maxResolution: Infinity,
- minResolution: 0
+ minResolution: 0,
+ minZoom: -Infinity,
+ maxZoom: Infinity
});
});
@@ -147,13 +149,17 @@ describe('ol.layer.Group', function() {
visible: false,
zIndex: 10,
maxResolution: 500,
- minResolution: 0.25
+ minResolution: 0.25,
+ minZoom: 1,
+ maxZoom: 10
});
expect(layerGroup.getOpacity()).to.be(0.5);
expect(layerGroup.getVisible()).to.be(false);
expect(layerGroup.getMaxResolution()).to.be(500);
expect(layerGroup.getMinResolution()).to.be(0.25);
+ expect(layerGroup.getMinZoom()).to.be(1);
+ expect(layerGroup.getMaxZoom()).to.be(10);
expect(layerGroup.getLayerState()).to.eql({
layer: layerGroup,
opacity: 0.5,
@@ -164,7 +170,9 @@ describe('ol.layer.Group', function() {
extent: undefined,
zIndex: 10,
maxResolution: 500,
- minResolution: 0.25
+ minResolution: 0.25,
+ minZoom: 1,
+ maxZoom: 10
});
expect(layerGroup.getLayers()).to.be.a(Collection);
expect(layerGroup.getLayers().getLength()).to.be(1);
@@ -206,7 +214,9 @@ describe('ol.layer.Group', function() {
extent: groupExtent,
zIndex: 0,
maxResolution: 500,
- minResolution: 0.25
+ minResolution: 0.25,
+ minZoom: -Infinity,
+ maxZoom: Infinity
});
expect(layerGroup.getLayers()).to.be.a(Collection);
expect(layerGroup.getLayers().getLength()).to.be(1);
@@ -237,6 +247,8 @@ describe('ol.layer.Group', function() {
layerGroup.setExtent(groupExtent);
layerGroup.setMaxResolution(500);
layerGroup.setMinResolution(0.25);
+ layerGroup.setMinZoom(5);
+ layerGroup.setMaxZoom(10);
expect(layerGroup.getLayerState()).to.eql({
layer: layerGroup,
opacity: 0.3,
@@ -247,7 +259,9 @@ describe('ol.layer.Group', function() {
extent: groupExtent,
zIndex: 10,
maxResolution: 500,
- minResolution: 0.25
+ minResolution: 0.25,
+ minZoom: 5,
+ maxZoom: 10
});
});
@@ -264,7 +278,9 @@ describe('ol.layer.Group', function() {
extent: undefined,
zIndex: 0,
maxResolution: Infinity,
- minResolution: 0
+ minResolution: 0,
+ minZoom: -Infinity,
+ maxZoom: Infinity
});
layerGroup.setOpacity(3);
@@ -279,7 +295,9 @@ describe('ol.layer.Group', function() {
extent: undefined,
zIndex: 0,
maxResolution: Infinity,
- minResolution: 0
+ minResolution: 0,
+ minZoom: -Infinity,
+ maxZoom: Infinity
});
});
@@ -452,12 +470,58 @@ describe('ol.layer.Group', function() {
extent: undefined,
zIndex: 0,
maxResolution: 150,
- minResolution: 0.25
+ minResolution: 0.25,
+ minZoom: -Infinity,
+ maxZoom: Infinity
});
layerGroup.dispose();
});
+ it('returns max minZoom', function() {
+ const group = new LayerGroup({
+ minZoom: 5,
+ layers: [
+ new Layer({
+ source: new Source({
+ projection: 'EPSG:4326'
+ })
+ }),
+ new Layer({
+ source: new Source({
+ projection: 'EPSG:4326'
+ }),
+ minZoom: 10
+ })
+ ]
+ });
+
+ expect(group.getLayerStatesArray()[0].minZoom).to.be(5);
+ expect(group.getLayerStatesArray()[1].minZoom).to.be(10);
+ });
+
+ it('returns min maxZoom of layers', function() {
+ const group = new LayerGroup({
+ maxZoom: 5,
+ layers: [
+ new Layer({
+ source: new Source({
+ projection: 'EPSG:4326'
+ })
+ }),
+ new Layer({
+ source: new Source({
+ projection: 'EPSG:4326'
+ }),
+ maxZoom: 2
+ })
+ ]
+ });
+
+ expect(group.getLayerStatesArray()[0].maxZoom).to.be(5);
+ expect(group.getLayerStatesArray()[1].maxZoom).to.be(2);
+ });
+
});
});
diff --git a/test/spec/ol/layer/layer.test.js b/test/spec/ol/layer/layer.test.js
index 655d923dbb..f7d6b5f4ee 100644
--- a/test/spec/ol/layer/layer.test.js
+++ b/test/spec/ol/layer/layer.test.js
@@ -1,5 +1,5 @@
import Map from '../../../../src/ol/Map.js';
-import Layer, {visibleAtResolution} from '../../../../src/ol/layer/Layer.js';
+import Layer, {inView} from '../../../../src/ol/layer/Layer.js';
import {get as getProjection} from '../../../../src/ol/proj.js';
import RenderEvent from '../../../../src/ol/render/Event.js';
import Source from '../../../../src/ol/source/Source.js';
@@ -43,6 +43,14 @@ describe('ol.layer.Layer', function() {
expect(layer.getMinResolution()).to.be(0);
});
+ it('provides default min zoom', function() {
+ expect(layer.getMinZoom()).to.be(-Infinity);
+ });
+
+ it('provides default max zoom', function() {
+ expect(layer.getMaxZoom()).to.be(Infinity);
+ });
+
it('provides default layerState', function() {
expect(layer.getLayerState()).to.eql({
layer: layer,
@@ -54,7 +62,9 @@ describe('ol.layer.Layer', function() {
extent: undefined,
zIndex: 0,
maxResolution: Infinity,
- minResolution: 0
+ minResolution: 0,
+ minZoom: -Infinity,
+ maxZoom: Infinity
});
});
@@ -72,6 +82,8 @@ describe('ol.layer.Layer', function() {
zIndex: 10,
maxResolution: 500,
minResolution: 0.25,
+ minZoom: 1,
+ maxZoom: 10,
foo: 42
});
@@ -79,6 +91,8 @@ describe('ol.layer.Layer', function() {
expect(layer.getVisible()).to.be(false);
expect(layer.getMaxResolution()).to.be(500);
expect(layer.getMinResolution()).to.be(0.25);
+ expect(layer.getMinZoom()).to.be(1);
+ expect(layer.getMaxZoom()).to.be(10);
expect(layer.get('foo')).to.be(42);
expect(layer.getLayerState()).to.eql({
layer: layer,
@@ -90,7 +104,9 @@ describe('ol.layer.Layer', function() {
extent: undefined,
zIndex: 10,
maxResolution: 500,
- minResolution: 0.25
+ minResolution: 0.25,
+ minZoom: 1,
+ maxZoom: 10
});
layer.dispose();
@@ -108,7 +124,7 @@ describe('ol.layer.Layer', function() {
});
});
- describe('visibleAtResolution', function() {
+ describe('inView', function() {
let layer;
beforeEach(function() {
@@ -123,36 +139,196 @@ describe('ol.layer.Layer', function() {
layer.dispose();
});
- it('returns false if layer is not visible', function() {
- layer.setVisible(false);
- layer.setMinResolution(3);
- layer.setMaxResolution(5);
- const layerState = layer.getLayerState();
- expect(visibleAtResolution(layerState, 4)).to.be(false);
- });
+ const cases = [{
+ when: 'layer is not visible',
+ visible: false,
+ view: {
+ resolution: 4, zoom: 4
+ },
+ inView: false
+ }, {
+ when: 'layer is not visible (with min/max zoom and resolution)',
+ visible: false,
+ minZoom: 2,
+ maxZoom: 6,
+ minResolution: 2,
+ maxResolution: 6,
+ view: {
+ resolution: 4, zoom: 4
+ },
+ inView: false
+ }, {
+ when: 'view zoom is less than minZoom',
+ minZoom: 2,
+ view: {
+ resolution: 1, zoom: 1
+ },
+ inView: false
+ }, {
+ when: 'view zoom is less than minZoom (with maxZoom)',
+ minZoom: 2,
+ maxZoom: 4,
+ view: {
+ resolution: 1, zoom: 1
+ },
+ inView: false
+ }, {
+ when: 'view zoom is equal to minZoom',
+ minZoom: 2,
+ view: {
+ resolution: 2, zoom: 2
+ },
+ inView: false
+ }, {
+ when: 'view zoom is equal to minZoom (with maxZoom)',
+ minZoom: 2,
+ maxZoom: 4,
+ view: {
+ resolution: 2, zoom: 2
+ },
+ inView: false
+ }, {
+ when: 'view zoom is greater than minZoom',
+ minZoom: 2,
+ view: {
+ resolution: 3, zoom: 3
+ },
+ inView: true
+ }, {
+ when: 'view zoom is greater than minZoom (with maxZoom)',
+ minZoom: 2,
+ maxZoom: 4,
+ view: {
+ resolution: 3, zoom: 3
+ },
+ inView: true
+ }, {
+ when: 'view zoom is equal to maxZoom',
+ maxZoom: 4,
+ view: {
+ resolution: 4, zoom: 4
+ },
+ inView: true
+ }, {
+ when: 'view zoom is equal to maxZoom (with minZoom)',
+ minZoom: 2,
+ maxZoom: 4,
+ view: {
+ resolution: 4, zoom: 4
+ },
+ inView: true
+ }, {
+ when: 'view zoom is greater than maxZoom',
+ maxZoom: 4,
+ view: {
+ resolution: 5, zoom: 5
+ },
+ inView: false
+ }, {
+ when: 'view zoom is greater than maxZoom (with minZoom)',
+ minZoom: 2,
+ maxZoom: 4,
+ view: {
+ resolution: 5, zoom: 5
+ },
+ inView: false
+ }, {
+ when: 'view resolution is less than minResolution',
+ minResolution: 2,
+ view: {
+ resolution: 1, zoom: 1
+ },
+ inView: false
+ }, {
+ when: 'view resolution is less than minResolution (with maxResolution)',
+ minResolution: 2,
+ maxResolution: 4,
+ view: {
+ resolution: 1, zoom: 1
+ },
+ inView: false
+ }, {
+ when: 'view resolution is equal to minResolution',
+ minResolution: 2,
+ view: {
+ resolution: 2, zoom: 2
+ },
+ inView: true
+ }, {
+ when: 'view resolution is equal to minResolution (with maxResolution)',
+ minResolution: 2,
+ maxResolution: 4,
+ view: {
+ resolution: 2, zoom: 2
+ },
+ inView: true
+ }, {
+ when: 'view resolution is greater than minResolution',
+ minResolution: 2,
+ view: {
+ resolution: 3, zoom: 3
+ },
+ inView: true
+ }, {
+ when: 'view resolution is greater than minResolution (with maxResolution)',
+ minResolution: 2,
+ maxResolution: 4,
+ view: {
+ resolution: 3, zoom: 3
+ },
+ inView: true
+ }, {
+ when: 'view resolution is equal to maxResolution',
+ maxResolution: 4,
+ view: {
+ resolution: 4, zoom: 4
+ },
+ inView: false
+ }, {
+ when: 'view resolution is equal to maxResolution (with minResolution)',
+ minResolution: 2,
+ maxResolution: 4,
+ view: {
+ resolution: 4, zoom: 4
+ },
+ inView: false
+ }, {
+ when: 'view resolution is greater than maxResolution',
+ maxResolution: 4,
+ view: {
+ resolution: 5, zoom: 5
+ },
+ inView: false
+ }, {
+ when: 'view resolution is greater than maxResolution (with minResolution)',
+ minResolution: 2,
+ maxResolution: 4,
+ view: {
+ resolution: 5, zoom: 5
+ },
+ inView: false
+ }];
- it('returns false if resolution lower than minResolution', function() {
- layer.setVisible(true);
- layer.setMinResolution(3);
- layer.setMaxResolution(5);
- const layerState = layer.getLayerState();
- expect(visibleAtResolution(layerState, 2)).to.be(false);
- });
-
- it('returns false if resolution greater than maxResolution', function() {
- layer.setVisible(true);
- layer.setMinResolution(3);
- layer.setMaxResolution(5);
- const layerState = layer.getLayerState();
- expect(visibleAtResolution(layerState, 6)).to.be(false);
- });
-
- it('returns true otherwise', function() {
- layer.setVisible(true);
- layer.setMinResolution(3);
- layer.setMaxResolution(5);
- const layerState = layer.getLayerState();
- expect(visibleAtResolution(layerState, 4)).to.be(true);
+ cases.forEach(function(c, i) {
+ it('returns ' + c.inView + ' when ' + c.when, function() {
+ if ('visible' in c) {
+ layer.setVisible(c.visible);
+ }
+ if ('minZoom' in c) {
+ layer.setMinZoom(c.minZoom);
+ }
+ if ('maxZoom' in c) {
+ layer.setMaxZoom(c.maxZoom);
+ }
+ if ('minResolution' in c) {
+ layer.setMinResolution(c.minResolution);
+ }
+ if ('maxResolution' in c) {
+ layer.setMaxResolution(c.maxResolution);
+ }
+ const layerState = layer.getLayerState();
+ expect(inView(layerState, c.view)).to.be(c.inView);
+ });
});
});
@@ -189,40 +365,24 @@ describe('ol.layer.Layer', function() {
extent: undefined,
zIndex: 10,
maxResolution: 500,
- minResolution: 0.25
+ minResolution: 0.25,
+ minZoom: -Infinity,
+ maxZoom: Infinity
});
});
it('returns a layerState with clamped values', function() {
layer.setOpacity(-1.5);
layer.setVisible(false);
- expect(layer.getLayerState()).to.eql({
- layer: layer,
- opacity: 0,
- visible: false,
- managed: true,
- hasOverlay: false,
- sourceState: 'ready',
- extent: undefined,
- zIndex: 0,
- maxResolution: Infinity,
- minResolution: 0
- });
+ let state = layer.getLayerState();
+ expect(state.opacity).to.be(0);
+ expect(state.visible).to.be(false);
layer.setOpacity(3);
layer.setVisible(true);
- expect(layer.getLayerState()).to.eql({
- layer: layer,
- opacity: 1,
- visible: true,
- managed: true,
- hasOverlay: false,
- sourceState: 'ready',
- extent: undefined,
- zIndex: 0,
- maxResolution: Infinity,
- minResolution: 0
- });
+ state = layer.getLayerState();
+ expect(state.opacity).to.be(1);
+ expect(state.visible).to.be(true);
});
});