diff --git a/elements/layercontrol/layercontrol.stories.js b/elements/layercontrol/layercontrol.stories.js index 0ac998813..4f44d250b 100644 --- a/elements/layercontrol/layercontrol.stories.js +++ b/elements/layercontrol/layercontrol.stories.js @@ -533,6 +533,61 @@ export const Tabs = { `, }; +/** + * Zoom layer state based on `minZoom` and `maxZoom`. + * The color change state only visible when `showZoomLayerState` is set inside layer properties. + */ +export const ZoomLayerState = { + args: { + showZoomLayerState: true, + }, + render: (args) => html` +
+ + + +
+ `, +}; + /** * Unstyled version of the Element */ diff --git a/elements/layercontrol/src/components/layer.js b/elements/layercontrol/src/components/layer.js index 01c725799..8769ade69 100644 --- a/elements/layercontrol/src/components/layer.js +++ b/elements/layercontrol/src/components/layer.js @@ -3,6 +3,10 @@ import { when } from "lit/directives/when.js"; import { live } from "lit/directives/live.js"; import "./layerTools"; import { checkbox } from "../../../../utils/styles/checkbox"; +import { + isLayerVisibleBasedOnZoomState, + isZoomLayerStateRequired, +} from "../helpers"; /** * A single layer display @@ -12,12 +16,19 @@ import { checkbox } from "../../../../utils/styles/checkbox"; export class EOxLayerControlLayer extends LitElement { static properties = { layer: { attribute: false }, + map: { attribute: false, state: true }, titleProperty: { attribute: "title-property", type: String }, + showZoomLayerState: { attribute: false, type: Boolean }, tools: { attribute: false }, unstyled: { type: Boolean }, noShadow: { type: Boolean }, }; + /** + * @type Boolean + */ + currLayerVisibilityBasedOnZoom = true; + constructor() { super(); @@ -28,11 +39,23 @@ export class EOxLayerControlLayer extends LitElement { */ this.layer = null; + /** + * The native OL map + * @type {import("ol").Map} + * @see {@link https://openlayers.org/en/latest/apidoc/module-ol_Map-Map.html} + */ + this.map = null; + /** * The layer title property */ this.titleProperty = "title"; + /** + * Show layer state based on zoom level or not + */ + this.showZoomLayerState = false; + /** * @type Array */ @@ -48,6 +71,52 @@ export class EOxLayerControlLayer extends LitElement { this.noShadow = true; } + /** + * Check and update layer visibility based on zoom level + * and only update DOM if visibility gets updated + */ + updateLayerZoomVisibility() { + const newLayerVisibilityBasedOnZoom = isLayerVisibleBasedOnZoomState( + this.layer, + this.map, + this.showZoomLayerState + ); + + let visibilityChanged = false; + + // Checking if visibility changed or not and updating `currLayerVisibilityBasedOnZoom` + if (!newLayerVisibilityBasedOnZoom && this.currLayerVisibilityBasedOnZoom) + (this.currLayerVisibilityBasedOnZoom = false), (visibilityChanged = true); + else if ( + newLayerVisibilityBasedOnZoom && + !this.currLayerVisibilityBasedOnZoom + ) + (this.currLayerVisibilityBasedOnZoom = true), (visibilityChanged = true); + + // if visibilityChanged trigger UI update + if (visibilityChanged) { + this.requestUpdate(); + this.dispatchEvent( + new CustomEvent("change:resolution", { bubbles: true }) + ); + } + } + + /** + * Check and update layer zoom visibility at beginning + * and register "change:resolution" ones at the beginning if `showZoomLayerState` is present + */ + firstUpdated() { + if (isZoomLayerStateRequired(this.layer, this.showZoomLayerState)) { + this.updateLayerZoomVisibility(); + + // Initialize change:resolution event ones + this.map + .getView() + .on("change:resolution", () => this.updateLayerZoomVisibility()); + } + } + createRenderRoot() { return this.noShadow ? this : super.createRenderRoot(); } @@ -61,7 +130,12 @@ export class EOxLayerControlLayer extends LitElement { ${when( this.layer, () => html` -
+