I have a layer that renders point features in a geojson source as circles. Here's an example of one of the features:
{
type: 'Feature',
properties: {
color: 'red',
red: true,
green: false
},
geometry: {
type: 'Point',
coordinates: [-77.038659, 38.931567]
}
};
I want circle-opacity to be a product of 3 factors (some properties on the features, map zoom, and a boolean in feature-state for whether that feature should be hidden). I can't figure out a way to write an expression that accounts for all three. Restrictions around zoom rules seem to be the issue.
Here's the logic I am trying to write:
if (feature-state.hidden) {
opacity = 0;
} else if (properties.red) {
opacity = 1;
} else if (properties.green and zoom >= 10) {
opacity = 1;
} else if (zoom >= 15) {
opacity = 1;
} else {
opacity = 0;
}
I tried writing an opacity expression like this:
'circle-opacity': [
'case',
['to-boolean', ['feature-state', 'hidden']], 0,
['to-boolean', ['get', 'red']], 1,
['to-boolean', ['get', 'green']], ['case', ['>=', ['zoom'], 10], 1, 0], // I could also write a permutation of this using an ['all'] rule
['>=', ['zoom'], 15], 1,
0,
],
That gets rejected with this message: "Error: layers.places.paint.circle-opacity: "zoom" expression may only be used as input to a top-level "step" or "interpolate" expression."
So then I tried something like this:
'circle-opacity': [
'step',
['zoom'],
0,
[
'case',
['to-boolean', ['get', 'red'], false], 1,
['to-boolean', ['get', 'green'], false], 10,
15
],
1
]
That gets rejected with this message: "Error: layers.places.paint.circle-opacity[3]: Input/output pairs for "step" expressions must be defined using literal numeric values (not computed expressions) for the input values."
As you can see, I hadn't even gotten around to adding the feature-state checks yet.
Here's a JSFiddle to play with: https://jsfiddle.net/rognstad/px4c8tbe/17/
I think I can make it work by breaking each color out into its own layer with a minZoom property and then only using an opacity expression for feature-state, but that feels really clunky and will result in worse performance.
It seems like there has to be a better way. Do you have any better suggestions for how to achieve this? Thanks!