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); }); });