Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"@mapbox/unitbezier": "^0.0.1",
"@mapbox/vector-tile": "^2.0.4",
"@mapbox/whoots-js": "^3.1.0",
"@maplibre/maplibre-gl-style-spec": "^24.3.1",
"@maplibre/maplibre-gl-style-spec": "git+https://github.com/melitele/maplibre-style-spec.git#global-state-visibility-dist",
"@maplibre/vt-pbf": "^4.0.3",
"@types/geojson": "^7946.0.16",
"@types/geojson-vt": "3.2.5",
Expand Down
5 changes: 5 additions & 0 deletions src/style/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ export class Style extends Evented {
const layer = this._layers[layerId];
const layoutAffectingGlobalStateRefs = layer.getLayoutAffectingGlobalStateRefs();
const paintAffectingGlobalStateRefs = layer.getPaintAffectingGlobalStateRefs();
const visibilityAffectingGlobalStateRefs = layer.getVisibilityAffectingGlobalStateRefs();

if (layoutAffectingGlobalStateRefs.has(ref)) {
sourceIdsToReload.add(layer.source);
Expand All @@ -379,6 +380,10 @@ export class Style extends Evented {
this._updatePaintProperty(layer, name, value);
}
}
if (visibilityAffectingGlobalStateRefs?.has(ref)) {
layer.recalculateVisibility();
this._updateLayer(layer);
}
}
}

Expand Down
43 changes: 36 additions & 7 deletions src/style/style_layer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {filterObject} from '../util/util';

import {featureFilter, latest as styleSpec, supportsPropertyExpression} from '@maplibre/maplibre-gl-style-spec';
import {createVisibilityExpression, featureFilter, latest as styleSpec, supportsPropertyExpression} from '@maplibre/maplibre-gl-style-spec';
import {
validateStyle,
validateLayoutProperty,
Expand All @@ -12,9 +12,14 @@ import {Layout, Transitionable, type Transitioning, type Properties, PossiblyEva

import type {Bucket, BucketParameters} from '../data/bucket';
import type Point from '@mapbox/point-geometry';
import type {FeatureFilter, FeatureState,
import type {
FeatureFilter,
FeatureState,
LayerSpecification,
FilterSpecification} from '@maplibre/maplibre-gl-style-spec';
FilterSpecification,
ExpressionSpecification,
VisibilitySpecification
} from '@maplibre/maplibre-gl-style-spec';
import type {TransitionParameters, PropertyValue} from './properties';
import {type EvaluationParameters} from './evaluation_parameters';
import type {CrossfadeParameters} from './evaluation_parameters';
Expand Down Expand Up @@ -87,7 +92,9 @@ export abstract class StyleLayer extends Evented {
minzoom: number;
maxzoom: number;
filter: FilterSpecification | void;
visibility: 'visible' | 'none' | void;
visibility: VisibilitySpecification | void;
private _visibility: 'visible' | 'none' | void;

_crossfadeParameters: CrossfadeParameters;

_unevaluatedLayout: Layout<any>;
Expand All @@ -99,6 +106,8 @@ export abstract class StyleLayer extends Evented {

_featureFilter: FeatureFilter;

_visibilityExpression: any;

readonly onAdd: ((map: Map) => void);
readonly onRemove: ((map: Map) => void);

Expand Down Expand Up @@ -127,6 +136,8 @@ export abstract class StyleLayer extends Evented {
this.minzoom = layer.minzoom;
this.maxzoom = layer.maxzoom;

this._visibilityExpression = createVisibilityExpression(this.visibility as VisibilitySpecification, globalState);

if (layer.type !== 'background') {
this.source = layer.source;
this.sourceLayer = layer['source-layer'];
Expand Down Expand Up @@ -179,6 +190,10 @@ export abstract class StyleLayer extends Evented {
getLayoutAffectingGlobalStateRefs(): Set<string> {
const globalStateRefs = new Set<string>();

for (const globalStateRef of this._visibilityExpression.getGlobalStateRefs()) {
globalStateRefs.add(globalStateRef);
}

if (this._unevaluatedLayout) {
for (const propertyName in this._unevaluatedLayout._values) {
const value = this._unevaluatedLayout._values[propertyName];
Expand Down Expand Up @@ -219,6 +234,14 @@ export abstract class StyleLayer extends Evented {
return globalStateRefs;
}

/**
* Get list of global state references that are used within visibility expression.
* This is used to determine if layer visibility needs to be updated when global state property changes.
*/
getVisibilityAffectingGlobalStateRefs() {
return this._visibilityExpression.getGlobalStateRefs();
}

setLayoutProperty(name: string, value: any, options: StyleSetterOptions = {}) {
if (value !== null && value !== undefined) {
const key = `layers.${this.id}.layout.${name}`;
Expand All @@ -229,6 +252,8 @@ export abstract class StyleLayer extends Evented {

if (name === 'visibility') {
this.visibility = value;
this._visibilityExpression.setValue(value);
this.recalculateVisibility();
return;
}

Expand Down Expand Up @@ -283,10 +308,10 @@ export abstract class StyleLayer extends Evented {
return false;
}

isHidden(zoom: number, roundMinZoom: boolean = false) {
isHidden(zoom: number = this.minzoom, roundMinZoom: boolean = false) {
if (this.minzoom && zoom < (roundMinZoom ? Math.floor(this.minzoom) : this.minzoom)) return true;
if (this.maxzoom && zoom >= this.maxzoom) return true;
return this.visibility === 'none';
return this.visibility === 'none' || this._visibility === 'none';
}

updateTransitions(parameters: TransitionParameters) {
Expand All @@ -297,6 +322,10 @@ export abstract class StyleLayer extends Evented {
return this._transitioningPaint.hasTransition();
}

recalculateVisibility() {
this._visibility = this._visibilityExpression.evaluate();
}

recalculate(parameters: EvaluationParameters, availableImages: Array<string>) {
if (parameters.getCrossfadeParameters) {
this._crossfadeParameters = parameters.getCrossfadeParameters();
Expand Down Expand Up @@ -325,7 +354,7 @@ export abstract class StyleLayer extends Evented {

if (this.visibility) {
output.layout = output.layout || {};
output.layout.visibility = this.visibility;
output.layout.visibility = this.visibility as ExpressionSpecification;
}

return filterObject(output, (value, key) => {
Expand Down
2 changes: 1 addition & 1 deletion src/style/style_layer/color_relief_style_layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,6 @@ export class ColorReliefStyleLayer extends StyleLayer {
}

hasOffscreenPass() {
return this.visibility !== 'none' && !!this.colorRampTextures;
return !this.isHidden() && !!this.colorRampTextures;
}
}
2 changes: 1 addition & 1 deletion src/style/style_layer/heatmap_style_layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,6 @@ export class HeatmapStyleLayer extends StyleLayer {
}

hasOffscreenPass() {
return this.paint.get('heatmap-opacity') !== 0 && this.visibility !== 'none';
return this.paint.get('heatmap-opacity') !== 0 && !this.isHidden();
}
}
2 changes: 1 addition & 1 deletion src/style/style_layer/hillshade_style_layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ export class HillshadeStyleLayer extends StyleLayer {
}

hasOffscreenPass() {
return this.paint.get('hillshade-exaggeration') !== 0 && this.visibility !== 'none';
return this.paint.get('hillshade-exaggeration') !== 0 && !this.isHidden();
}
}
2 changes: 1 addition & 1 deletion src/style/style_layer_index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export class StyleLayerIndex {
const layers = layerConfigs.map((layerConfig) => this._layers[layerConfig.id]);

const layer = layers[0];
if (layer.visibility === 'none') {
if (layer.isHidden()) {
continue;
}

Expand Down
Loading