mapbox gl data driven style: What does the "value" parameter do? - mapbox

I'm modifying my icon size based on the current zoom value by using the zoom data to drive the size.
As I understand it, I'm using the property "zoom" to track the zoom value (This is required as per the spec), In the stops I setup each desired "zoom" value and then output the icon-size value for that state (shown by the 0-1 > 3 range). If I don't include the parameter "value": something the code fails. If I set it all to 1, it works fine, so it seems that this value is ignored.
Can anyone explain its actual use?
// Add layer to map populating data from Geojson
map.addLayer({
"id": "seed",
"type": "symbol",
"source": "objects",
"layout": {
"icon-rotation-alignment": "map",
"icon-keep-upright": true,
"icon-rotate": 0,
"icon-image": "{icon}",
"icon-allow-overlap": true,
"icon-size": {
"property": "zoom",
"type": "exponential",
"stops": [
[{ "zoom": 15, "value": 1}, 0.1],
[{ "zoom": 16, "value": 1}, 0.3],
[{ "zoom": 17, "value": 1}, 0.6],
[{ "zoom": 18, "value": 1}, 0.8],
[{ "zoom": 19, "value": 1}, 2],
[{ "zoom": 20, "value": 1}, 3]
]
}
}
});
});

Apologies for the confusion #stuffyjoelab!
There are three types of functions in Mapbox GL:
Zoom functions allow the appearance of a map feature to change with map’s zoom level
Property functions allow the appearance of a map feature to change with its properties.
Zoom-and-property functions allow the appearance of a map feature to change with both its properties and zoom.
(There's more info about these in our style spec docs)
I'm using the property "zoom" to track the zoom value
We define a "property" as being per-feature metadata, a la GeoJSON feature properties. By this definition, zoom is not a property (unless you have a property on your features called zoom)
If you switch to the zoom function syntax by removing "property": "zoom" and replacing the {zoom, value} objects from your stops with numeric zooms, everything should work as expected.
// Add layer to map populating data from Geojson
map.addLayer({
"id": "seed",
"type": "symbol",
"source": "objects",
"layout": {
"icon-rotation-alignment": "map",
"icon-keep-upright": true,
"icon-rotate": 0,
"icon-image": "{icon}",
"icon-allow-overlap": true,
"icon-size": {
"type": "exponential",
"stops": [
[15, 0.1],
[16, 0.3],
[17, 0.6],
[18, 0.8],
[19, 2],
[20, 3]
]
}
}
});

Related

mapbox-gl-draw data driven style on LineString

I use Mapbox GL Draw and I want to customize the fill color of my LineString Feature using data driven.
I have a set userProperties: true and I have a property prefixed with user_ .
here is my style configuration :
{
id: "gl-draw-linestring-fill-inactive",
type: "fill",
filter: ["all", ["==", "active", "false"], ["==", "$type", "LineString"],["!=", "mode", "static"],],
paint: {
"fill-color": [
"case",
["==", ["get", "user_type"], "meetingRoom"],
"#00ff00",
["==", ["get", "user_type"], "notUsed"],
"#00ff00",
"#ff0000",
],
"fill-outline-color": "#3bb2d0",
"fill-opacity": 0.4,
},
}
and my feature :
{
"type": "Feature",
"id": "ROOM-floor-1-1",
"properties": {
"parentId": "floor-1",
"user_type": "notUsed"
},
"geometry": {
"coordinates": [
[2.334699793548168, 48.85506145052912],
[2.3334337908935083, 48.85340956808176],
[2.3360301692199243, 48.85314130852265],
[2.3368884761040363, 48.85547088304844],
[2.3368884761040363, 48.85547088304844],
[2.334699793548168, 48.85506145052912]
],
"type": "LineString"
}
}
Feature is always paint with default value (#ff0000). It should be #00ff00 in this example.
In the same application I use the same property (user_type) to set Line color on Polygon and it works fine !
Any Idea ?
I just figured out how to do it, I'm putting the answer here in case other people make the same mistake as me.
I misunderstood the mapbox documentation for using my own properties in data driven styles.
If you want to use a property named myProp from your feature, you have to prefix it with user_ but only in the style rule.
For example:
{
"type": "Feature",
"id": "1",
"properties": {
"myProp": "myValue"
},
"geometry": {
"coordinates": [...],
"type": "LineString"
}
}
And:
{
id: 'my-rule',
type: 'line',
filter: ['all', ['==', 'active', 'false'], ['==', '$type', 'LineString'],['!=', 'mode', 'static']],
paint: {
'line-color': [
'match', ['get', 'user_myProp'], // get the property
'myValue', '#00ff00',
'#ff0000']
},
}
My mistake was to add prefix user_ in the style rule AND the feature properties.
I dont really understand, why you are using "type: fill" in your style configuration for a linestring. You shoud be using the line-specific style properties as shown in this mapbox example https://docs.mapbox.com/mapbox-gl-js/example/data-driven-lines/
Also, since you are refering to a property in your data driven styling, there is no need to use the "case". you can simply use "match"
So it would rather be:
{
id: 'gl-draw-linestring-fill-inactive',
type: 'line',
filter: ['all', ['==', 'active', 'false'], ['==', '$type', 'LineString'],['!=', 'mode', 'static']],
paint: {
'line-color': [
'match', ['get', 'user_type'], // get the property
'meetingRoom', '#00ff00',
'notUsed', '#00ff00',
'#ff0000'],
'line-width': 3,
},
}
By the way: ids on feature level should be integers or strings, that can be cast in as integers:
https://github.com/mapbox/mapbox-gl-js/issues/7632

Symbol placed with line-center doesn't rotate as the map rotates

I'm having a problem rotating an image with property symbol-placement set to line-center.
This is what it looks like
Removing the property half-solve the issue; the icon rotate as I rotate the map, but they position at the start of the line, and it's not what I'm trying to do.
The definition of my layer is:
{
"id": "my_symbol",
"type": "symbol",
"source": "XXXX",
"source-layer": "XXXXXXX",
"minzoom": 19,
"layout": {
"symbol-placement": "line-center",
"icon-size": {
"stops": [
[20, 0.2],
[21, 0.1],
[22, 0.3],
[23, 0.5],
[24, 0.7]
]
},
"icon-image": [
"concat",
"edge_",
["get", "status_list"]
],
"icon-allow-overlap": true
}
}
I'm trying to achieve this behaviour only by the layer's definition.
I tried looking for a solution, here on SO and on some other sites but I haven't found anything that would help me.
you can set your icon rotation with icon-rotation-alignment
setting it to viewport will fix the icon rotation to your viewport while setting it to map won't rotate it
i'm sorry the gif is hard to see!
{
"id": "my_symbol",
"type": "symbol",
"source": "XXXX",
"source-layer": "XXXXXXX",
"minzoom": 19,
"layout": {
"symbol-placement": "line-center",
"icon-size": {
"stops": [
[20, 0.2],
[21, 0.1],
[22, 0.3],
[23, 0.5],
[24, 0.7]
]
},
"icon-image": [
"concat",
"edge_",
["get", "status_list"]
],
"icon-allow-overlap": true,
"symbol-placement": "line-center",
"icon-rotation-alignment": "viewport"
}
}

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).

Possible to show a subset of the points using one datalayer with mapbox-gl-js?

I have datalayer consisting of points/ markers in Mapbox-gl-js. When I would like to split my points into categories I can use data-styling, for example like this:
"source-layer": "sf2010",
"paint": {
"circle-radius": {
"base": 1.75,
"stops": [[12, 2], [22, 180]]
},
"circle-color": {
property: 'ethnicity',
type: 'categorical',
stops: [
['White', "#fbb03b"],
['Black', '#223b53'],
['Hispanic', '#e55e5e'],
['Asian', '#3bb2d0'],
['Other', '#ccc']]
}
It seems, using one datalayer, all points (possibly with different category-stylings) will be included on the map. I can style a category of points to not show by giving it a circle-radius of zero, but then it still reacts to clicks etc. Or is there a way to really present a subset of the points using one datalayer?
As Molly suggested, you want a filter:
"source-layer": "sf2010",
"paint": {
"circle-radius": {
"base": 1.75,
"stops": [[12, 2], [22, 180]]
},
"circle-color": {
property: 'ethnicity',
type: 'categorical',
stops: [
['White', "#fbb03b"],
['Black', '#223b53'],
['Hispanic', '#e55e5e'],
['Asian', '#3bb2d0'],
['Other', '#ccc']]
}
},
"filter": ['!==', 'ethnicity','Martian']

Styling markers from GeoJSON based on non-string feature properties in Mapbox

as the title suggests, I would like to style some markers stored in a GeoJSON file. In each feature, I saved a "rotate": some_integer, based on how I want to rotate the marker.
In the stylejson in Mapbox I wrote the following style for the markers:
{
"id": "markers_test",
"type": "symbol",
"source": "markers_test",
"layout": {
"symbol-placement": "point",
"icon-image": "marker_{style_id}",
"icon-rotate": "{rotate}",
"text-field": "{name}",
"text-font": ["Open Sans Semibold"],
"text-anchor": "top-left",
"text-padding": 20,
"text-size": 10,
"text-optional": true
},
"paint": {
"text-color": "#dddddd",
"text-halo-color": "#0000ff",
"text-halo-width": 1,
"text-halo-blur": 1
}
}
Setting the correct name and icon works flawlessly, but as soon as I try to set up rotate, it crashes saying the value should be a number, not a string. Only - how do i reference a property of a feature outside a string?
The {token} syntax only works for text-field and icon-image. For all other properties you must use the property function syntax.
{
"id": "markers_test",
"type": "symbol",
"source": "markers_test",
"layout": {
"symbol-placement": "point",
"icon-image": "marker_{style_id}",
"icon-rotate": {
"property": "rotate",
"stops": [[0, 0], [365, 365]]
},
"text-field": "{name}",
"text-font": ["Open Sans Semibold"],
"text-anchor": "top-left",
"text-padding": 20,
"text-size": 10,
"text-optional": true
},
"paint": {
"text-color": "#dddddd",
"text-halo-color": "#0000ff",
"text-halo-width": 1,
"text-halo-blur": 1
}
}