Support zoom limits for layers
This commit is contained in:
13
examples/layer-zoom-limits.html
Normal file
13
examples/layer-zoom-limits.html
Normal file
@@ -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"
|
||||||
|
---
|
||||||
|
<div id="map" class="map"></div>
|
||||||
33
examples/layer-zoom-limits.js
Normal file
33
examples/layer-zoom-limits.js
Normal file
@@ -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 ' +
|
||||||
|
'<a href="http://www.maptiler.com/">MapTiler</a>',
|
||||||
|
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
|
||||||
|
})
|
||||||
|
});
|
||||||
@@ -7,7 +7,7 @@ import {CLASS_CONTROL, CLASS_UNSELECTABLE, CLASS_COLLAPSED} from '../css.js';
|
|||||||
import {removeChildren, replaceNode} from '../dom.js';
|
import {removeChildren, replaceNode} from '../dom.js';
|
||||||
import {listen} from '../events.js';
|
import {listen} from '../events.js';
|
||||||
import EventType from '../events/EventType.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 visibleAttributions = [];
|
||||||
|
|
||||||
const layerStatesArray = frameState.layerStatesArray;
|
const layerStatesArray = frameState.layerStatesArray;
|
||||||
const resolution = frameState.viewState.resolution;
|
|
||||||
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
||||||
const layerState = layerStatesArray[i];
|
const layerState = layerStatesArray[i];
|
||||||
if (!visibleAtResolution(layerState, resolution)) {
|
if (!inView(layerState, frameState.viewState)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ import {assign} from '../obj.js';
|
|||||||
* visible.
|
* visible.
|
||||||
* @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will
|
* @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will
|
||||||
* be visible.
|
* 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;
|
options.maxResolution !== undefined ? options.maxResolution : Infinity;
|
||||||
properties[LayerProperty.MIN_RESOLUTION] =
|
properties[LayerProperty.MIN_RESOLUTION] =
|
||||||
options.minResolution !== undefined ? options.minResolution : 0;
|
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}
|
* @type {string}
|
||||||
@@ -103,6 +111,8 @@ class BaseLayer extends BaseObject {
|
|||||||
state.zIndex = this.getZIndex() || (state.managed === false ? Infinity : 0);
|
state.zIndex = this.getZIndex() || (state.managed === false ? Infinity : 0);
|
||||||
state.maxResolution = this.getMaxResolution();
|
state.maxResolution = this.getMaxResolution();
|
||||||
state.minResolution = Math.max(this.getMinResolution(), 0);
|
state.minResolution = Math.max(this.getMinResolution(), 0);
|
||||||
|
state.minZoom = this.getMinZoom();
|
||||||
|
state.maxZoom = this.getMaxZoom();
|
||||||
this.state_ = state;
|
this.state_ = state;
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
@@ -161,6 +171,26 @@ class BaseLayer extends BaseObject {
|
|||||||
return /** @type {number} */ (this.get(LayerProperty.MIN_RESOLUTION));
|
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 the opacity of the layer (between 0 and 1).
|
||||||
* @return {number} The opacity of the layer.
|
* @return {number} The opacity of the layer.
|
||||||
@@ -231,6 +261,30 @@ class BaseLayer extends BaseObject {
|
|||||||
this.set(LayerProperty.MIN_RESOLUTION, minResolution);
|
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.
|
* Set the opacity of the layer, allowed values range from 0 to 1.
|
||||||
* @param {number} opacity The opacity of the layer.
|
* @param {number} opacity The opacity of the layer.
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ import SourceState from '../source/State.js';
|
|||||||
* visible.
|
* visible.
|
||||||
* @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will
|
* @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will
|
||||||
* be visible.
|
* 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("./Base.js").default>|import("../Collection.js").default<import("./Base.js").default>} [layers] Child layers.
|
* @property {Array<import("./Base.js").default>|import("../Collection.js").default<import("./Base.js").default>} [layers] Child layers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -215,6 +219,10 @@ class LayerGroup extends BaseLayer {
|
|||||||
layerState.maxResolution, ownLayerState.maxResolution);
|
layerState.maxResolution, ownLayerState.maxResolution);
|
||||||
layerState.minResolution = Math.max(
|
layerState.minResolution = Math.max(
|
||||||
layerState.minResolution, ownLayerState.minResolution);
|
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 (ownLayerState.extent !== undefined) {
|
||||||
if (layerState.extent !== undefined) {
|
if (layerState.extent !== undefined) {
|
||||||
layerState.extent = getIntersection(layerState.extent, ownLayerState.extent);
|
layerState.extent = getIntersection(layerState.extent, ownLayerState.extent);
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ import SourceState from '../source/State.js';
|
|||||||
* @property {number} zIndex
|
* @property {number} zIndex
|
||||||
* @property {number} maxResolution
|
* @property {number} maxResolution
|
||||||
* @property {number} minResolution
|
* @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
|
* Return `true` if the layer is visible and if the provided view state
|
||||||
* between the layer's minResolution and maxResolution. The comparison is
|
* has resolution and zoom levels that are in range of the layer's min/max.
|
||||||
* inclusive for `minResolution` and exclusive for `maxResolution`.
|
|
||||||
* @param {State} layerState Layer state.
|
* @param {State} layerState Layer state.
|
||||||
* @param {number} resolution Resolution.
|
* @param {import("../View.js").State} viewState View state.
|
||||||
* @return {boolean} The layer is visible at the given resolution.
|
* @return {boolean} The layer is visible at the given view state.
|
||||||
*/
|
*/
|
||||||
export function visibleAtResolution(layerState, resolution) {
|
export function inView(layerState, viewState) {
|
||||||
return layerState.visible && resolution >= layerState.minResolution &&
|
if (!layerState.visible) {
|
||||||
resolution < layerState.maxResolution;
|
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;
|
export default Layer;
|
||||||
|
|||||||
@@ -12,5 +12,7 @@ export default {
|
|||||||
Z_INDEX: 'zIndex',
|
Z_INDEX: 'zIndex',
|
||||||
MAX_RESOLUTION: 'maxResolution',
|
MAX_RESOLUTION: 'maxResolution',
|
||||||
MIN_RESOLUTION: 'minResolution',
|
MIN_RESOLUTION: 'minResolution',
|
||||||
|
MAX_ZOOM: 'maxZoom',
|
||||||
|
MIN_ZOOM: 'minZoom',
|
||||||
SOURCE: 'source'
|
SOURCE: 'source'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @module ol/renderer/Composite
|
* @module ol/renderer/Composite
|
||||||
*/
|
*/
|
||||||
import {CLASS_UNSELECTABLE} from '../css.js';
|
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 RenderEvent from '../render/Event.js';
|
||||||
import RenderEventType from '../render/EventType.js';
|
import RenderEventType from '../render/EventType.js';
|
||||||
import MapRenderer from './Map.js';
|
import MapRenderer from './Map.js';
|
||||||
@@ -95,7 +95,7 @@ class CompositeMapRenderer extends MapRenderer {
|
|||||||
const layerStatesArray = frameState.layerStatesArray.sort(function(a, b) {
|
const layerStatesArray = frameState.layerStatesArray.sort(function(a, b) {
|
||||||
return a.zIndex - b.zIndex;
|
return a.zIndex - b.zIndex;
|
||||||
});
|
});
|
||||||
const viewResolution = frameState.viewState.resolution;
|
const viewState = frameState.viewState;
|
||||||
|
|
||||||
this.children_.length = 0;
|
this.children_.length = 0;
|
||||||
let hasOverlay = false;
|
let hasOverlay = false;
|
||||||
@@ -104,7 +104,7 @@ class CompositeMapRenderer extends MapRenderer {
|
|||||||
const layerState = layerStatesArray[i];
|
const layerState = layerStatesArray[i];
|
||||||
hasOverlay = hasOverlay || layerState.hasOverlay;
|
hasOverlay = hasOverlay || layerState.hasOverlay;
|
||||||
frameState.layerIndex = i;
|
frameState.layerIndex = i;
|
||||||
if (!visibleAtResolution(layerState, viewResolution) ||
|
if (!inView(layerState, viewState) ||
|
||||||
(layerState.sourceState != SourceState.READY && layerState.sourceState != SourceState.UNDEFINED)) {
|
(layerState.sourceState != SourceState.READY && layerState.sourceState != SourceState.UNDEFINED)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -142,7 +142,6 @@ class CompositeMapRenderer extends MapRenderer {
|
|||||||
*/
|
*/
|
||||||
forEachLayerAtPixel(pixel, frameState, hitTolerance, callback, layerFilter) {
|
forEachLayerAtPixel(pixel, frameState, hitTolerance, callback, layerFilter) {
|
||||||
const viewState = frameState.viewState;
|
const viewState = frameState.viewState;
|
||||||
const viewResolution = viewState.resolution;
|
|
||||||
|
|
||||||
const layerStates = frameState.layerStatesArray;
|
const layerStates = frameState.layerStatesArray;
|
||||||
const numLayers = layerStates.length;
|
const numLayers = layerStates.length;
|
||||||
@@ -150,7 +149,7 @@ class CompositeMapRenderer extends MapRenderer {
|
|||||||
for (let i = numLayers - 1; i >= 0; --i) {
|
for (let i = numLayers - 1; i >= 0; --i) {
|
||||||
const layerState = layerStates[i];
|
const layerState = layerStates[i];
|
||||||
const layer = layerState.layer;
|
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 layerRenderer = layer.getRenderer();
|
||||||
const data = layerRenderer.getDataAtPixel(pixel, frameState, hitTolerance);
|
const data = layerRenderer.getDataAtPixel(pixel, frameState, hitTolerance);
|
||||||
if (data) {
|
if (data) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {abstract, getUid} from '../util.js';
|
|||||||
import Disposable from '../Disposable.js';
|
import Disposable from '../Disposable.js';
|
||||||
import {getWidth} from '../extent.js';
|
import {getWidth} from '../extent.js';
|
||||||
import {TRUE} from '../functions.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 {shared as iconImageCache} from '../style/IconImageCache.js';
|
||||||
import {compose as composeTransform, makeInverse} from '../transform.js';
|
import {compose as composeTransform, makeInverse} from '../transform.js';
|
||||||
import {renderDeclutterItems} from '../render.js';
|
import {renderDeclutterItems} from '../render.js';
|
||||||
@@ -87,7 +87,6 @@ class MapRenderer extends Disposable {
|
|||||||
) {
|
) {
|
||||||
let result;
|
let result;
|
||||||
const viewState = frameState.viewState;
|
const viewState = frameState.viewState;
|
||||||
const viewResolution = viewState.resolution;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {boolean} managed Managed layer.
|
* @param {boolean} managed Managed layer.
|
||||||
@@ -126,7 +125,7 @@ class MapRenderer extends Disposable {
|
|||||||
for (i = numLayers - 1; i >= 0; --i) {
|
for (i = numLayers - 1; i >= 0; --i) {
|
||||||
const layerState = layerStates[i];
|
const layerState = layerStates[i];
|
||||||
const layer = /** @type {import("../layer/Layer.js").default} */ (layerState.layer);
|
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 layerRenderer = layer.getRenderer();
|
||||||
const source = layer.getSource();
|
const source = layer.getSource();
|
||||||
if (layerRenderer && source) {
|
if (layerRenderer && source) {
|
||||||
|
|||||||
@@ -44,7 +44,9 @@ describe('ol.layer.Group', function() {
|
|||||||
extent: undefined,
|
extent: undefined,
|
||||||
zIndex: 0,
|
zIndex: 0,
|
||||||
maxResolution: Infinity,
|
maxResolution: Infinity,
|
||||||
minResolution: 0
|
minResolution: 0,
|
||||||
|
minZoom: -Infinity,
|
||||||
|
maxZoom: Infinity
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -147,13 +149,17 @@ describe('ol.layer.Group', function() {
|
|||||||
visible: false,
|
visible: false,
|
||||||
zIndex: 10,
|
zIndex: 10,
|
||||||
maxResolution: 500,
|
maxResolution: 500,
|
||||||
minResolution: 0.25
|
minResolution: 0.25,
|
||||||
|
minZoom: 1,
|
||||||
|
maxZoom: 10
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(layerGroup.getOpacity()).to.be(0.5);
|
expect(layerGroup.getOpacity()).to.be(0.5);
|
||||||
expect(layerGroup.getVisible()).to.be(false);
|
expect(layerGroup.getVisible()).to.be(false);
|
||||||
expect(layerGroup.getMaxResolution()).to.be(500);
|
expect(layerGroup.getMaxResolution()).to.be(500);
|
||||||
expect(layerGroup.getMinResolution()).to.be(0.25);
|
expect(layerGroup.getMinResolution()).to.be(0.25);
|
||||||
|
expect(layerGroup.getMinZoom()).to.be(1);
|
||||||
|
expect(layerGroup.getMaxZoom()).to.be(10);
|
||||||
expect(layerGroup.getLayerState()).to.eql({
|
expect(layerGroup.getLayerState()).to.eql({
|
||||||
layer: layerGroup,
|
layer: layerGroup,
|
||||||
opacity: 0.5,
|
opacity: 0.5,
|
||||||
@@ -164,7 +170,9 @@ describe('ol.layer.Group', function() {
|
|||||||
extent: undefined,
|
extent: undefined,
|
||||||
zIndex: 10,
|
zIndex: 10,
|
||||||
maxResolution: 500,
|
maxResolution: 500,
|
||||||
minResolution: 0.25
|
minResolution: 0.25,
|
||||||
|
minZoom: 1,
|
||||||
|
maxZoom: 10
|
||||||
});
|
});
|
||||||
expect(layerGroup.getLayers()).to.be.a(Collection);
|
expect(layerGroup.getLayers()).to.be.a(Collection);
|
||||||
expect(layerGroup.getLayers().getLength()).to.be(1);
|
expect(layerGroup.getLayers().getLength()).to.be(1);
|
||||||
@@ -206,7 +214,9 @@ describe('ol.layer.Group', function() {
|
|||||||
extent: groupExtent,
|
extent: groupExtent,
|
||||||
zIndex: 0,
|
zIndex: 0,
|
||||||
maxResolution: 500,
|
maxResolution: 500,
|
||||||
minResolution: 0.25
|
minResolution: 0.25,
|
||||||
|
minZoom: -Infinity,
|
||||||
|
maxZoom: Infinity
|
||||||
});
|
});
|
||||||
expect(layerGroup.getLayers()).to.be.a(Collection);
|
expect(layerGroup.getLayers()).to.be.a(Collection);
|
||||||
expect(layerGroup.getLayers().getLength()).to.be(1);
|
expect(layerGroup.getLayers().getLength()).to.be(1);
|
||||||
@@ -237,6 +247,8 @@ describe('ol.layer.Group', function() {
|
|||||||
layerGroup.setExtent(groupExtent);
|
layerGroup.setExtent(groupExtent);
|
||||||
layerGroup.setMaxResolution(500);
|
layerGroup.setMaxResolution(500);
|
||||||
layerGroup.setMinResolution(0.25);
|
layerGroup.setMinResolution(0.25);
|
||||||
|
layerGroup.setMinZoom(5);
|
||||||
|
layerGroup.setMaxZoom(10);
|
||||||
expect(layerGroup.getLayerState()).to.eql({
|
expect(layerGroup.getLayerState()).to.eql({
|
||||||
layer: layerGroup,
|
layer: layerGroup,
|
||||||
opacity: 0.3,
|
opacity: 0.3,
|
||||||
@@ -247,7 +259,9 @@ describe('ol.layer.Group', function() {
|
|||||||
extent: groupExtent,
|
extent: groupExtent,
|
||||||
zIndex: 10,
|
zIndex: 10,
|
||||||
maxResolution: 500,
|
maxResolution: 500,
|
||||||
minResolution: 0.25
|
minResolution: 0.25,
|
||||||
|
minZoom: 5,
|
||||||
|
maxZoom: 10
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -264,7 +278,9 @@ describe('ol.layer.Group', function() {
|
|||||||
extent: undefined,
|
extent: undefined,
|
||||||
zIndex: 0,
|
zIndex: 0,
|
||||||
maxResolution: Infinity,
|
maxResolution: Infinity,
|
||||||
minResolution: 0
|
minResolution: 0,
|
||||||
|
minZoom: -Infinity,
|
||||||
|
maxZoom: Infinity
|
||||||
});
|
});
|
||||||
|
|
||||||
layerGroup.setOpacity(3);
|
layerGroup.setOpacity(3);
|
||||||
@@ -279,7 +295,9 @@ describe('ol.layer.Group', function() {
|
|||||||
extent: undefined,
|
extent: undefined,
|
||||||
zIndex: 0,
|
zIndex: 0,
|
||||||
maxResolution: Infinity,
|
maxResolution: Infinity,
|
||||||
minResolution: 0
|
minResolution: 0,
|
||||||
|
minZoom: -Infinity,
|
||||||
|
maxZoom: Infinity
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -452,12 +470,58 @@ describe('ol.layer.Group', function() {
|
|||||||
extent: undefined,
|
extent: undefined,
|
||||||
zIndex: 0,
|
zIndex: 0,
|
||||||
maxResolution: 150,
|
maxResolution: 150,
|
||||||
minResolution: 0.25
|
minResolution: 0.25,
|
||||||
|
minZoom: -Infinity,
|
||||||
|
maxZoom: Infinity
|
||||||
});
|
});
|
||||||
|
|
||||||
layerGroup.dispose();
|
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);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import Map from '../../../../src/ol/Map.js';
|
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 {get as getProjection} from '../../../../src/ol/proj.js';
|
||||||
import RenderEvent from '../../../../src/ol/render/Event.js';
|
import RenderEvent from '../../../../src/ol/render/Event.js';
|
||||||
import Source from '../../../../src/ol/source/Source.js';
|
import Source from '../../../../src/ol/source/Source.js';
|
||||||
@@ -43,6 +43,14 @@ describe('ol.layer.Layer', function() {
|
|||||||
expect(layer.getMinResolution()).to.be(0);
|
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() {
|
it('provides default layerState', function() {
|
||||||
expect(layer.getLayerState()).to.eql({
|
expect(layer.getLayerState()).to.eql({
|
||||||
layer: layer,
|
layer: layer,
|
||||||
@@ -54,7 +62,9 @@ describe('ol.layer.Layer', function() {
|
|||||||
extent: undefined,
|
extent: undefined,
|
||||||
zIndex: 0,
|
zIndex: 0,
|
||||||
maxResolution: Infinity,
|
maxResolution: Infinity,
|
||||||
minResolution: 0
|
minResolution: 0,
|
||||||
|
minZoom: -Infinity,
|
||||||
|
maxZoom: Infinity
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -72,6 +82,8 @@ describe('ol.layer.Layer', function() {
|
|||||||
zIndex: 10,
|
zIndex: 10,
|
||||||
maxResolution: 500,
|
maxResolution: 500,
|
||||||
minResolution: 0.25,
|
minResolution: 0.25,
|
||||||
|
minZoom: 1,
|
||||||
|
maxZoom: 10,
|
||||||
foo: 42
|
foo: 42
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -79,6 +91,8 @@ describe('ol.layer.Layer', function() {
|
|||||||
expect(layer.getVisible()).to.be(false);
|
expect(layer.getVisible()).to.be(false);
|
||||||
expect(layer.getMaxResolution()).to.be(500);
|
expect(layer.getMaxResolution()).to.be(500);
|
||||||
expect(layer.getMinResolution()).to.be(0.25);
|
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.get('foo')).to.be(42);
|
||||||
expect(layer.getLayerState()).to.eql({
|
expect(layer.getLayerState()).to.eql({
|
||||||
layer: layer,
|
layer: layer,
|
||||||
@@ -90,7 +104,9 @@ describe('ol.layer.Layer', function() {
|
|||||||
extent: undefined,
|
extent: undefined,
|
||||||
zIndex: 10,
|
zIndex: 10,
|
||||||
maxResolution: 500,
|
maxResolution: 500,
|
||||||
minResolution: 0.25
|
minResolution: 0.25,
|
||||||
|
minZoom: 1,
|
||||||
|
maxZoom: 10
|
||||||
});
|
});
|
||||||
|
|
||||||
layer.dispose();
|
layer.dispose();
|
||||||
@@ -108,7 +124,7 @@ describe('ol.layer.Layer', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('visibleAtResolution', function() {
|
describe('inView', function() {
|
||||||
let layer;
|
let layer;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
@@ -123,36 +139,196 @@ describe('ol.layer.Layer', function() {
|
|||||||
layer.dispose();
|
layer.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns false if layer is not visible', function() {
|
const cases = [{
|
||||||
layer.setVisible(false);
|
when: 'layer is not visible',
|
||||||
layer.setMinResolution(3);
|
visible: false,
|
||||||
layer.setMaxResolution(5);
|
view: {
|
||||||
const layerState = layer.getLayerState();
|
resolution: 4, zoom: 4
|
||||||
expect(visibleAtResolution(layerState, 4)).to.be(false);
|
},
|
||||||
});
|
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() {
|
cases.forEach(function(c, i) {
|
||||||
layer.setVisible(true);
|
it('returns ' + c.inView + ' when ' + c.when, function() {
|
||||||
layer.setMinResolution(3);
|
if ('visible' in c) {
|
||||||
layer.setMaxResolution(5);
|
layer.setVisible(c.visible);
|
||||||
const layerState = layer.getLayerState();
|
}
|
||||||
expect(visibleAtResolution(layerState, 2)).to.be(false);
|
if ('minZoom' in c) {
|
||||||
});
|
layer.setMinZoom(c.minZoom);
|
||||||
|
}
|
||||||
it('returns false if resolution greater than maxResolution', function() {
|
if ('maxZoom' in c) {
|
||||||
layer.setVisible(true);
|
layer.setMaxZoom(c.maxZoom);
|
||||||
layer.setMinResolution(3);
|
}
|
||||||
layer.setMaxResolution(5);
|
if ('minResolution' in c) {
|
||||||
const layerState = layer.getLayerState();
|
layer.setMinResolution(c.minResolution);
|
||||||
expect(visibleAtResolution(layerState, 6)).to.be(false);
|
}
|
||||||
});
|
if ('maxResolution' in c) {
|
||||||
|
layer.setMaxResolution(c.maxResolution);
|
||||||
it('returns true otherwise', function() {
|
}
|
||||||
layer.setVisible(true);
|
const layerState = layer.getLayerState();
|
||||||
layer.setMinResolution(3);
|
expect(inView(layerState, c.view)).to.be(c.inView);
|
||||||
layer.setMaxResolution(5);
|
});
|
||||||
const layerState = layer.getLayerState();
|
|
||||||
expect(visibleAtResolution(layerState, 4)).to.be(true);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -189,40 +365,24 @@ describe('ol.layer.Layer', function() {
|
|||||||
extent: undefined,
|
extent: undefined,
|
||||||
zIndex: 10,
|
zIndex: 10,
|
||||||
maxResolution: 500,
|
maxResolution: 500,
|
||||||
minResolution: 0.25
|
minResolution: 0.25,
|
||||||
|
minZoom: -Infinity,
|
||||||
|
maxZoom: Infinity
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns a layerState with clamped values', function() {
|
it('returns a layerState with clamped values', function() {
|
||||||
layer.setOpacity(-1.5);
|
layer.setOpacity(-1.5);
|
||||||
layer.setVisible(false);
|
layer.setVisible(false);
|
||||||
expect(layer.getLayerState()).to.eql({
|
let state = layer.getLayerState();
|
||||||
layer: layer,
|
expect(state.opacity).to.be(0);
|
||||||
opacity: 0,
|
expect(state.visible).to.be(false);
|
||||||
visible: false,
|
|
||||||
managed: true,
|
|
||||||
hasOverlay: false,
|
|
||||||
sourceState: 'ready',
|
|
||||||
extent: undefined,
|
|
||||||
zIndex: 0,
|
|
||||||
maxResolution: Infinity,
|
|
||||||
minResolution: 0
|
|
||||||
});
|
|
||||||
|
|
||||||
layer.setOpacity(3);
|
layer.setOpacity(3);
|
||||||
layer.setVisible(true);
|
layer.setVisible(true);
|
||||||
expect(layer.getLayerState()).to.eql({
|
state = layer.getLayerState();
|
||||||
layer: layer,
|
expect(state.opacity).to.be(1);
|
||||||
opacity: 1,
|
expect(state.visible).to.be(true);
|
||||||
visible: true,
|
|
||||||
managed: true,
|
|
||||||
hasOverlay: false,
|
|
||||||
sourceState: 'ready',
|
|
||||||
extent: undefined,
|
|
||||||
zIndex: 0,
|
|
||||||
maxResolution: Infinity,
|
|
||||||
minResolution: 0
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user