Does mapbox setPaintProperty method process expressions? - mapbox

Does mapbox setPaintProperty method process expressions?
map.setPaintProperty('places',
'circle-radius',
[
'interpolate',
['linear'],
['number', ["get", "Time", ['object', ["get", "Day", ['object', ["get", "Stats"]]]]]],
0, 4,
5, 24
]
);
I get an error saying:
Error: layers.places.paint.circle-radius[2][1][1]: Expected string but found number instead.
I find the error confusing as I would think it should be returning a number.
I am somewhat certain the following expression works as I use it when implementing my addLayer()
paint: {
'circle-radius': [
'interpolate',
['linear'],
['number', ["get", "Time", ['object', ["get", "Day", ['object', ["get", "Stats"]]]]]],
0, 4,
5, 24
],'circle-opacity': 0.8
}
Any help would be great.

Does mapbox setPaintProperty method process expressions?
Yes, I've used setPaintProperty with interpolate expressions without an issue.

Related

Mapbox GL JS - Change the color of selected 3D buildings

in my database I have ID numbers (mapbox) of about a million buildings, each building is associated with a category.
Buildings are scattered all over the world.
There can be many more buildings, so the data should be downloaded dynamically (json, geojson, etc.).
I would like to change the color of 3D buildings (fill-extrusion-color) depending on the category and add an icon next to it.
I have been browsing the documentation but I am not able to combine it into a solution.
I am asking for help as I should solve this problem.
Currently, it only controls color like this:
'fill-extrusion-color': [ "case", [ "! =", ["get", "min_height"], 0 ], "hsl (224, 18%, 56%)", [ "match", ["get", "type"], ["building: part"], true, false ], "hsl (224, 25%, 38%)", [ "interpolate", ["linear"], ["get", "height"], 0, "hsl (224.47%, 29%)", twenty, "hsl (224.61%, 33%)", 50, "hsl (224.53%, 48%)", 400, "hsl (224, 83%, 72%)" ] ]
Can you try:
'fill-extrusion-color':
[ "case",
[ "!=", ["get", "min_height"], 0 ],
"#7b85a3",
[ "match", ["get", "type"],
["building: part"], true, false ],
"#495679",
[ "interpolate", ["linear"],
["get", "height"],
0, "hsl (224, 47%, 29%)",
12, "hsl (224, 61%, 33%)",
50, "hsl (224, 53%, 48%)",
400, "hsl (224, 83%, 72%)" ] ]

Visibility of villages in Mapbox

In my Mapbox GL project, I have a layer with towns and villages which looks like this:
{
"id": "towns",
"type": "symbol",
"source": "composite",
"source-layer": "place_label",
"minzoom": 1,
"maxzoom": 14,
"filter": [
"all",
[
"match",
["get", "type"],
["town", "village", "hamlet"],
true,
false
],
["match", ["get", "name"], [
// list of villages
], true, false]
],
"layout": {
"text-variable-anchor": ["top", "bottom", "left", "right"],
"text-allow-overlap": true,
"text-ignore-placement": true,
"icon-allow-overlap": true,
"text-field": ["get", "name"],
"text-font": ["Roboto Regular", "Arial Unicode MS Regular"],
"text-size": [
"interpolate",
["linear"],
["zoom"],
3,
8,
22,
16
]
},
"paint": {
"text-halo-color": "hsla(0, 0%, 100%, 0.95)",
"text-halo-width": 1,
"text-halo-blur": 0.4
}
},
The text-size zoom interpolation works fine for the towns. However, the village will only show up after a zoomlevel of 9. Is there any way I could make the villages visible at all time?
Most likely, the Mapbox Streets Tileset you're using only includes those villages in the data after zoom 9, so there is nothing you can do in the style to make it show up earlier.
You'd need to create your own dataset which includes the data you want at lower zoom levels (and maybe just check this is the cause first in Mapbox Studio data view).

Using feature state for icon image, but expression parser is complaining

I am trying to use a feature state in a case statement for an icon-image with a zoom step, but the parser is refusing to take it, even though there should only be one at a time, am I missing something here?
layout: {
'icon-image': ["case",
["boolean", ["feature-state", "hover"], false],
['step', ['zoom'], 'marker-13', 7, 'marker-17'],
['step', ['zoom'], 'active-marker-13', 7, 'active-marker-17']
],
'icon-size': 1
},
Error received:
Only one zoom-based "step" or "interpolate" subexpression may be used in an expression.
Using 1.6.0.
TIA.
As the message is indicating, you can't have two separate ['zoom'] expressions.
You can solve this by flipping your expression inside out so the zoom is on the outside.
{
layout: {
'icon-image': ['step', ['zoom'],
['case',
["boolean", ["feature-state", "hover"], false],
'marker-13',
'active-marker-13'
],
7,
['case',
["boolean", ["feature-state", "hover"], false],
'marker-17',
'active-marker-17'
]
]
}
}

Extrude land in MapBox

I am trying to emphasize the fact that the land is higher than the water in my map so wanted to add an extrusion to the land layer. I thought taking the https://docs.mapbox.com/mapbox-gl-js/example/3d-buildings/ of the one with buildings and changing the layer source to 'land' would work but it didn't. Is this something specific to building layers or am I doing something wrong? Here is my layer definition in my style JSON:
{
"id": "3d-land",
"source": "composite",
"source-layer": "land", # Changed this from building
"filter": ["==", "extrude", "true"],
"type": "fill-extrusion",
"minzoom": 0,
"paint": {
"fill-extrusion-color": "#000",
"fill-extrusion-height": [
"interpolate", ["linear"], ["zoom"],
15, 0,
18.0, 30.0
],
"fill-extrusion-base": [
"interpolate", ["linear"], ["zoom"],
15, 0,
18.0, ["get", "min_height"]
],
"fill-extrusion-opacity": 0.8
}
}
First reason is as the console says, "land" does not exist on source "composite". "land" layer is background layer which is exist separately in the style. You cannot use fill-extrusion for background layer. You may want to use layers which use "compose" source.
The other reason is from filter. "filter": ["==", "extrude", "true"] means filtering if the value of layer's property called "extrude" is "true". land layer doesn't have a property extrude so it's always false.
So, the result of fix would be looks like:
map.addLayer(
{
id: "3d-landcover",
source: "composite",
"source-layer": "landcover",
"type": "fill-extrusion",
"minzoom": 0,
"paint": {
"fill-extrusion-color": "#000",
"fill-extrusion-height": [
"interpolate", ["linear"], ["zoom"],
15, 0,
18.0, 30.0
],
"fill-extrusion-base": [
"interpolate", ["linear"], ["zoom"],
15, 0,
18.0, ["get", "min_height"]
],
"fill-extrusion-opacity": 0.8
}
}
);
As the first reason, all the layers except water should be added as above if you want to make the land higher than water. it's not very effective.

nested expression in mapbox

I have an expression that I am using in a mapbox map to decide which icon I want to show. It looks like this:
"icon-image": [
"case",
["==", ["get", "matched"], "True"],
"greenmarkertick",
"redmarkercross",
]
I need to add another condition to this expression, as when matched is True but something else doesn't match, in this case:
["!=", ["get", "vehicle"], ["get", "standstill_vehicle"]]
I have tried adding this directly to my case expression, like so:
"icon-image": [
"case",
["==", ["get", "matched"], "True"],
"greenmarker",
["!=", ["get", "vehicle"], ["get", "standstill_vehicle"]],
"orangemarker",
"redmarker",
]
but this didn't work.
Basically what I need is an expression that checks if the the matched property is true and then checks to see if the vehicle properties match.
If they do display a green marker, if they don't display an orange marker. If matched is false then a red marker should be displayed.
Any help with this would be much appreciated.
I realised that the positioning of the expressions in the case expression does matter. So , I solved my problem with the following expression:
"icon-image": [
"case",
["all", ["==", ["get", "matched"], "True"], ["!=", ["get", "vehicle"], ["get", "standstill_vehicle"]]],
"orangemarker",
["==", ["get", "matched"], "True"],
"greenmarker",
"redmarker",
]