The way I've typically seen mapboxgl fill properties work on choropleth maps is something like this:
map.on('load', function () {
map.addSource('bb', { type: 'geojson', data: data, generateId: true});
map.addLayer({
'id': 'berlin',
'type': 'fill',
'source': 'bb',
'paint': {
'fill-color': {
'property': some_numeric_val,
'stops': [[4, '#feebe2'], [8, '#fbb4b9'], [12, '#f768a1'], [16, '#c51b8a'], [20, '#7a0177']]
},
'fill-opacity': .65
}
});
map.addLayer({
'id': 'berlin-stroke',
'type': 'line',
'source': 'bb',
'paint': {
'line-color': '#000',
'line-width': [
'case',
['boolean', ['feature-state', 'hover'], false],
2,
.5
]
}
});
});
i.e. the colors are created based on a property that the user selects. However, it seems like mapboxgl's default behavior is to interpolate colors. For example, if one of my geographic units has a value is somewhere between the breakpoints, mapboxgl will interpolate the color, resulting in a gradient of colors.
Is there a way to make the colors distinct (non-interpolated)? i.e. if value is 4 or less, the color is #feebe2, if the value is 8 or less, the color is '#fbb4b9', for a total of 5 discrete colors in the example I have here.
You can use step expressions.
Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of input and output values ("stops"). The input may be any numeric expression (e.g., ["get", "population"]). Stop inputs must be numeric literals in strictly ascending order. Returns the output value of the stop just less than the input, or the first output if the input is less than the first stop.
Syntax
["step",
input: number,
stop_output_0: OutputType,
stop_input_1: number, stop_output_1: OutputType,
stop_input_n: number, stop_output_n: OutputType, ...
]: OutputType
Reference : Sample example from mapbox which demonstrate similar requirement as mentioned in question.
You can try updating your code like below.
map.addLayer({
'id': 'berlin',
'type': 'fill',
'source': 'bb',
'paint': {
'fill-color': [
// Use step expressions (https://docs.mapbox.com/style-spec/reference/expressions/#step)
'step',
// Replace some_numeric_val by required property name from which you want to get the value.
['get', 'some_numeric_val'], // input: number,
// Set color which is expected to fill when value is less than 5, since 5 is first step value (stop_input_1) which is mentioned in next parameter value.
// stop_output_0: OutputType,
'#feebe2',
// Property value & required color to apply from given value till Property value mentioned in next step.
// stop_input_1: number, stop_output_1: OutputType,
// For current example #fbb4b9 will for value between 5 to 8.
5, '#fbb4b9',
// Property value & required color to apply from given value till Property value mentioned in next step.
// stop_input_2: number, stop_output_2: OutputType,
// For current example #f768a1 will for value between 9 to 12.
9, '#f768a1',
// Property value & required color to apply from given value till Property value mentioned in next step.
// stop_input_3: number, stop_output_3: OutputType,
// For current example #c51b8a will for value between 13 to 16.
13, '#c51b8a',
// Property value & required color to apply from given value till Property value mentioned in next step.
// stop_input_4: number, stop_output_4: OutputType,
// For current example #7a0177 will for value between 17 to 20.
17, '#7a0177',
// Property value & required color to apply from given value till Property value mentioned in next step.
// stop_input_5: number, stop_output_5: OutputType
// For current example #7a0177 will for value >= 21
21, '#7a0177'
],
'fill-opacity': .65
}
});