Skip to main content

Styling your layers

Work with expressions

In the Maps SDK, you can specify the value for any layout property, paint property, or filter as an expression. Expressions define how one or more feature property value or the current zoom level are combined using logical, mathematical, string, or color operations to produce the appropriate style property value or filter decision.

A property expression is any expression defined using a reference to feature property data. Property expressions allow the appearance of a feature to change with its properties. They can be used to visually differentiate types of features within the same layer or create data visualizations.

A camera expression is any expression defined using ['zoom']. Such expressions allow the appearance of a layer to change with the map’s zoom level. Zoom expressions can be used to create the illusion of depth and control data density.

There are countless ways to apply property expressions to your application, including:

  • Data-driven styling: Specify style rules based on one or more data attribute.
  • Arithmetic: Do arithmetic on source data, for example performing calculations to convert units.
  • Conditional logic: Use if-then logic, for example to decide exactly what text to display for a label based on which properties are available in the feature or even the length of the name.
  • String manipulation: Take control over label text with things like uppercase, lowercase, and title case transforms without having to edit, re-prepare and re-upload your data.
RELATED
Mapbox Style Specification: Expressions

An expression defines a formula for computing the value of the property using the operators described in this section.

Syntax

The Maps SDK's Style domain-specific language (DSL) allows you to write expressions in a block that is applied to a receiver class. DSL functions for expressions are provided to construct the instances. Expressions follow this format:

expression_name {
argument_0
argument_1
}

The expression_name is the expression operator, for example, you would use product to multiply two arguments or switchCase to create conditional logic.

The arguments are either literal (numbers, strings, or boolean values) or else themselves expressions. The number of arguments varies based on the expression.

Here's one example using an expression to calculate an arithmetic expression (π * 32):

product {
pi()
pow {
literal(3)
literal(2)
}
}

This example uses a product expression to multiply two arguments. The first argument is pi, which is an expression that returns the mathematical constant pi. The second arguement is another expression: a pow expression with two arguments of its own. It will return 32, and the result will be multiplied by π.

Expression types

  • Mathematical operators for performing arithmetic and other operations on numeric values
  • Logical operators for manipulating boolean values and making conditional decisions
  • String operators for manipulating strings
  • Data operators for providing access to the properties of source features
  • Camera operators for providing access to the parameters defining the current map view

Data-driven styling at runtime

You can use expressions to determine the style of features in a layer based on data properties in the source data. For example, if you have a source containing point data from individual responses to the 2010 U.S. Census and each point has an "ethnicity" data property, you can use expressions to specify the color of each circle based on reported ethnicity.

The example below uses the match expression to compare the value of the "ethnicity" data property for each point in the source to several possible values. The first argument of the match expression is the value of the "ethnicity" data property. There are several arguments that specify what to do if the value of the data property matches a given string and a final argument that specifies what to do if the value of the data property does not match any of the strings provided.

To read the values of the "ethnicity" data property, this example uses the get expression with "ethnicity" as the sole argument.

Then, it uses stop expressions for the next several arguments for the match expression. Each stop has two arguments: the first is the value to compare to the value of the "ethnicity" data property and the second is the value that should be applied to the layer's circleColor property if the value of the data property matches the first argument.

The second argument of the stop expression is a color, which is constructed using the rgb expression.

The final argument of the match expression is a fallback value that should be applied to circleColor if the value of the "ethnicity" data property does not match any of the strings provided.


style {
+circleLayer("population", "ethnicity-source") {
sourceLayer("sf2010")
...
circleColor(
// Compare value of the "ethnicity" data property
// to several possible values
match {
// Read the value of the "ethnicity" data property
get("ethnicity")
// If the value of the data property
// matches "white", then apply this color.
stop {
literal("white")
rgb(251.0, 176.0, 59.0)
}
// If the value of the data property
// matches "Black", then apply this color.
stop {
literal("Black")
rgb(34.0, 59.0, 83.0)
}
// If the value of the data property
// matches "Hispanic", then apply this color.
stop {
literal("Hispanic")
rgb(229.0, 94.0, 94.0)
}
// If the value of the data property
// matches "Asian", then apply this color.
stop {
literal("Asian")
rgb(59.0, 59.0, 208.0)
}
// If the value of the data property
// matches "Other", then apply this color.
stop {
literal("Other")
rgb(204.0, 204.0, 204.0)
}
// If the value of the "ethnicity" property does
// not match any of the above strings, use this color
rgb(0.0, 0.0, 0.0)
}
)
}
}
EXAMPLE
Style circles categorically

Add point data to a style from a vector tileset and use the match and get expressions to assign the color of each point in a CircleLayer based on a data property.

For more examples of expressions for data-driven styling, see the Maps SDK test application on GitHub.

Zoom-driven styling at runtime

You can use expressions to determine the style of features in a layer based on the camera position, including the zoom level. For example, if you have dense point data displayed using a circle layer, you may want to adjust the radius of circles based on the zoom level to make the data more readable at low zoom levels.

The example below uses the interpolate expression to produce a continuous, smooth series of values between pairs of input and output values ("stops"). Its first argument sets the interpolation type, the second is the value of the zoom level, and the remaining arguments specify the size of the circle radius that should be applied based on the value of the zoom level.

"Exponential" is one of a few types of interpolation available Mapbox expressions. The exponential expression has one argument: the base, which controls the rate at which the output increases.

The zoom expression does not require any arguments. It will return the value of the current zoom level of the map.

The remaining arguments of the interpolate expression are stops. They represent points along the exponential curve. When a user is viewing the map at zoom level 12 or below, the circles will have a radius of 2. When viewing it at zoom level 22 and above, the circles will have a radius of 180. For all zoom levels between, the radius will be determined by an exponential function and the value will fall somewhere between 2 and 180.


style {
+circleLayer("population", "ethnicity-source") {
sourceLayer("sf2010")
...
circleRadius(
// Produce a continuous, smooth series of values
// between pairs of input and output values
interpolate {
// Set the interpolation type
exponential {
literal(1.75)
}
// Get current zoom level
zoom()
// If the map is at zoom level 12 or below,
// set circle radius to 2
stop {
literal(12)
literal(2)
}
// If the map is at zoom level 22 or above,
// set circle radius to 180
stop {
literal(22)
literal(180)
}
}
)
}
}

For more examples of expressions for zoom-driven styling, see the Maps SDK test application on GitHub.

Light-driven styling in Standard

Mapbox Standard and Mapbox Standard Satellite uses 3D lighting which affects the entire map, like lighting in the real world. This means that when you switch to dark lights, for example to the “night” preset, your layers will also be dark. If you want to change how light affects the layers you have created, you will need to configure *-emissive-strength, a property which controls how light is being emitted. *-emissive-strength applies to background, fill, circle, symbol and line layer types.

Here’s an example how you would set *-emissive-strength for a line layer:


mapView.mapboxMap.getStyle { style ->
style.addSource(
vectorSource("vector-source") {
url("mapbox://mapbox.mapbox-streets-v8")
}
)
style.addLayer(
lineLayer("my-line-layer", "vector-source") {
sourceLayer("road")
lineEmissiveStrength(1.0)
slot("middle")
}
)
}

This image illustrates how different line-emissive-strength values are impacting the visual appearance of a line layer:

Was this page helpful?