Style expressions reference for custom layers
- Introduction
- Query Expressions
- Conditional Expressions
- Comparison Expressions
- Build Expressions
- Conversion Expressions
- Scale Expressions
- Math Expressions
Style expressions are used in style to filter and configure style rules.
A style expression is represented in JSON as an array whereas first argument is an expression name, and the rest of the entries are expression arguments.
[name, argument1, ...argumentN]
An expression argument can be either a value type or an expression.
Value types
null
The null type is a special type that can have only one value: null.
Example: null
boolean
The boolean type can only hold the values true or false.
Example: true
number
The number type stores a real number.
Example: -23.5
Example: 4
color
The color type stores a renderable color. A color value can be represented as a vector of numbers or a string.
Supported element count for a vector is 3 ([r,g,b]) or 4 ([r,g,b,a]) with elements in range [0, 1].
Supported string formats are:
- hex format "#rgb", "#rgba", "#rrggbb", and "#rrggbbaa" with r,g,b,a in range [0-9, a-f].
- css color functions "rgb(r,g,b)", "rgba(r,g,b,a)", "hsl(h,s,l)", "hsla(h,s,l,a)" with r,g,b in range [0, 255], a,s,l in range [0, 1] and h in range [0,360]. Values outside the ranges are clamped to the range boundary.
Example: "#00ff7f" -> Color(0, 255, 127, 255) (SpringGreen)
Example: "#f0f" -> Color(255, 0, 255, 255) (Magenta)
Example: "rgba(255, 99, 71, 44)" -> Color(255, 99, 71, 44) (Tomato with alpha 44)
string
The string type stores a sequence of characters.
Example: "string_theory"
vector2d
The vector2d type stores a 2d vector of numbers. To create a vector2d value, use make-vector expression.
Example: ["make-vector", 10, 20] // returns [10, 20]
vector3d
The vector3d type stores a 3d vector of numbers. To create a vector3d value, use make-vector expression.
Example: ["make-vector", 4.5, 5.5, 6.7] // returns [4.5, 5.5, 6.7]
vector4d
The vector4d type stores a 4d vector of numbers. To create a vector4d value, use make-vector expression.
Example: ["make-vector", -2, 4, 90, -234] // return [-2, 4, 90, -234]
array
The array type stores an array of value types. To create an array value use literal expression.
Example: ["literal", [1, 2] ] // returns an aray of real numbers.
Example: ["literal", [1, "2", 3] ] // returns an array of numbers and strings
dictionary
The dictionary type stores key-value pairs. The dictionary can be queried using get and has expressions.
To create a dictionary value use literal expression.
Example: ["literal", {"a": 1, "b": 2}]
NoteWhenever an expression argument can be of more than one value type, we use
valuefor that argument.
ref
References a value definition or an expression definition that can be evaluated to a value. Returns null if the definition cannot be found.
["ref", string]
Example:
"definitions" : {
"my_definition_1": 4,
"my_definition_2": true,
"my definiton_3": ["+", 1, 2]
}
["ref", "my_definition_1"] // returns 4
["ref", "my_definition_2"] // returns true
["ref", "my_definition_3"] // returns 3
["ref", "my_definition_4"] // returns null, the definition cannot be found.
get
Gets the property value of the current feature or a dictionary. Returns null if the property is not present. By feature, we understand a stylable map item, like roads, polygons etc.
["get", name] // `name` can be an expression, but that disables optimization and evaluation will be much slower.
["get", name, dictionary]
Examples:
To illustrate the use of get expression, let us consider a case where the rendered map contains a layer called 'Roads'.
Each feature (i.e. road) in the layer contains the property "road_width", expressed in meters.
Ideally we would like to use the "road_width" property of each feature in the style. To do that, we employ the
get expression. In the style below we set the style attribute "width" to the value of "road_width" property. In this manner, each styled line will have the width
that is defined in the "road_width" property.
{
"styles": [
{
"layer": "Roads",
"technique": "line",
"attr": {
"width": ["get", "road_width"] // returns the width in meter of the current road
}
}
]
}
In the following example, literal returns a dictionary with two keys "a" and "b". get expression will return the value of key "a"
["get", "a", ["literal", {"a": 1, "b": 2}]] // returns 1
has
Returns a boolean indicating if the current feature or the given dictionary has the specified property. By feature, we understand a stylable map item, like roads, polygons etc.
["has", name] // `name` can be an expression, but that disables optimization and evaluation will be much slower.
["has", name, dictionary]
Examples:
To illustrate the use of has expression, let us consider again the case where the rendered map contains a layer called 'Roads'.
This time though not all features in the layer contains the property "road_width", expressed in meters. Some do, some don't.
Ideally we would like to use the "road_width" property of each feature in the style, but what can we do for the features that do not have the "road_width" property?
In this case, we employ has expression to check which feature has "road_width" and which not. For the ones that do not contain "road_width", we set a default line width.
{
"styles": [
{
"layer": "Roads",
"technique": "line",
"attr": {
"width": [ "case"
["has", "road_width"], // returns true if the current road has "road_width" property
["get", "road_width"], // if the current road has "road_width" property, we set line width to "road_width" value
10 ] // else we set the line width to 10 meters
}
}
]
}
In the following example, literal returns an dictionary with two keys "a" and "b". has expression will return true.
["has", "a", ["literal", {"a": 1, "b": 2}]] // returns true
!has
Returns a boolean indicating if the current feature or the given dictionary does not have the specified property. By feature, we understand a stylable map item, like roads, polygons etc.
["!has", name]
["!has", name, dictionary]
The !has expression is equivalent to the negation of the has expression:
["!has", name] /* is same as */ ["!", ["has", name]]
["!has", name, dictionary] /* is same as */ ["!", ["has", name, object]]
inside-range
Returns true if input is inside any of the ranges, false if input in not inside any of the ranges
or 'null' if the input or the ranges are invalid or empty.
The ranges can be specified as a list of values, with each 2 consecutive values starting at an odd position
defining a range (range*StartMin - range*End) or through a sub expression that evaluates to a list of values.
The list must contain an even number of values with a minimum of 2.
Each range is start inclusive and end exclusive ([range*Start, range*End)).
["inside-range", input,
range1Start, range1End,
...
rangeNStart, rangeNEnd
]
["inside-range", input,
["literal", [range1Start, range1End, ... rangeNStart, rangeNEnd]]
]
Examples
["zoom"] returns 8.5
["inside-range", ["zoom"], 8.0, 9.0, 19.0, 20.0] // returns true
["inside-range", ["zoom"], 6.0, 7.0, 20.0, 21.0] // returns false
["inside-range", ["zoom"], 8.0, 9.0, 19.0] // returns null and logs "Inside-range function expects 2 or an even number of range arguments."
["inside-range", ["zoom"]] // returns null and logs "Inside-range function expects at least 2 arguments."
["inside-range"] // returns null and logs "Inside-range function expects at least 2 arguments."
["inside-range", ["zoom"], ["literal", [8.0, 9.0, 19.0, 20.0]]] // returns true
["inside-range", ["zoom"], ["literal", [6.0, 7.0, 20.0, 21.0]]] // returns false
zoom
Gets the current zoom level.
["zoom"]
all
Returns true if all the sub expressions evaluate to true.
["all", expression...] // boolean
Example:
"definitions" : {
"my_condition_1": true,
"my_condition_2": false,
"my_condition_3": true
}
["all",
["ref", "my_condition_1"],
["ref", "my_condition_2"],
["ref", "my_condition_3"]
] // returns false since my_condition_2 is false
any
Returns true if any sub expression evaluates to true.
["any", expression...] // boolean
Example:
"definitions" : {
"my_condition_1": true,
"my_condition_2": false,
"my_condition_3": true
}
["any",
["ref", "my_condition_1"],
["ref", "my_condition_2"],
["ref", "my_condition_3"]
] // returns true since my_condition_1 is true
none
Returns true if no sub expression evaluates to true.
["none", expression...]
Example:
"definitions" : {
"my_condition_1": true,
"my_condition_2": false,
"my_condition_3": true
}
["none",
["ref", "my_condition_1"],
["ref", "my_condition_2"],
["ref", "my_condition_3"]
] // returns false since my_condition_1 is true
match
Compares value with the labels and returns the result of the first match.
If the value doesn't match any label fallback will be returned. A label
must be a number, a string, or an array of those. If value and label differ in type, then fallback will be returned.
["match",
value,
label1, result1,
...
labelN, resultN,
fallback
]
Example:
"definitions" : {
"my_value": 10
}
["match",
["ref", "my_value"],
20,
"Value is 20", // result 1
10,
"Value is 10", // result 2
"No match was found" // fallback value
] // returns "Value is 10"
case
Evaluates the conditions in order and returns the first result where the condition evaluates to true.
The fallback will be returned if no conditions evaluates to true.
["case",
condition1, result1,
...
conditionN, resultN,
fallback
]
Example:
"definitions" : {
"my_condition_1": false,
"my_condition_2": false,
"my_condition_3": true
}
["case",
["ref", "my_condition_1"],
10,
["ref", "my_condition_2"],
20,
["ref", "my_condition_3"],
40,
80 // fallback value
] // returns 40 since my_condition_3 is true
==
Returns true if the values are equal. boolean, number, string, vector2d, vector3d, vector4d, array and dictionary types are supported.
["==", value, value]
!=
Returns true if the values are not equal. boolean, number, string, vector2d, vector3d, vector4d, array and dictionary types are supported.
["!=", value, value]
<
Returns true if the first value is less than the second value. boolean, number and string types are supported.
["<", value, value]
>
Returns true if the first value is greater than the second value. boolean, number and string types are supported.
[">", value, value]
<=
Returns true if the first value is less than or equal to the second value. boolean, number and string types are supported.
["<=", value, value]
>=
Returns true if the first value is greater than or equal to the second value. boolean, number and string types are supported.
[">=", value, value]
rgb
Creates a color from the RGB components. The components must be integers between 0 and 255. Values outside the range are clamped to the range border.
["rgb", number, number, number]
Example
["rgb", 1, 2, 3] // returns Color(1, 2, 3, 255)
rgba
Creates a color from the RGBA components. The r, g, b components must be integers within range [0, 255]. The a component must be within range [0, 1]. Values outside the range are clamped to the range border.
["rgba", number, number, number, number]
Example
["rgba", 1, 2, 3, 4] // returns Color(1, 2, 3, 4)
hsl
Creates a color from the HSL components:
- hue value in degrees between 0 and 360
- saturation value between 0 and 1
- lightness value between 0 and 1
["hsl", number, number, number]
Example
["hsl", 180, 0.5, 0.5] // returns Color(64, 191, 191, 250)
hsla
Creates a color from the HSLA components:
- hue value in degrees between 0 and 360
- saturation value between 0 and 1
- lightness value between 0 and 1
- alpha value between 0 and 1
["hsla", number, number, number, number]
Example
["hsla", 180, 0.5, 0.5, 0.5] // returns Color(64, 191, 191, 128)
literal
Returns a dictionary or an array as specified in json_document.
["literal", json_document]
Example:
["literal", {"a": 1, "b": 2}] // returns a dictionry with keys "a" and "b"
["literal", [1, 2, 3]] // returns an array
make-vector
Constructs two, three, or four dimensional vector from numbers.
["make-vector", number, number]
["make-vector", number, number, number]
["make-vector", number, number, number, number]
Examples:
["make-vector", 10, 20] // returns [10, 20]
["make-vector", 4.5, 5.5, 6.7] // returns [4.5, 5.5, 6.7]
["make-vector", -2, 4, 90, -234] // return [-2, 4, 90, -234]
["make-vector", 10, "20"] // returns null, does not support strings
!
Returns false if its value can be converted to true; otherwise, returns true. Value types supported are boolean, number, color, string, vector2d, vector3d, vector4d, gradient, array and dictionary.
["!", value]
to-color
Converts the string to color.
["to-color", string]
Examples:
["to-color", ["+", "#", "01020304"]] // returns Color(1, 2, 3, 4)
["to-color", ["get", "line_color"]] // if ["get", "line_color"] returns a string #01020304 then to-color will return Color(1, 2, 3, 4)
["to-color", "#01020304"] // returns Color(1, 2, 3, 4) but this conversion is not necessary since the style evaluator recognizes automatically "#01020304" as color
pixel-world-scale
- visibility: public
Converts a number of screen pixels to world units(meters).
["pixel-world-scale", number]
Example
Let's consider the case where the user wants to render a polyline with a width of 10 screen pixels. Given that the width attribute of the line techniques requires meters, the straight forward way to render a polyline with a width of 10 screen pixels is by using pixel-world-scale.
{
"styles": [
{
"layer": "MyRoads",
"technique": "line",
"attr": {
"width": ["pixel-world-scale", 10.0] // returns the width in meter that is equivalent to 10 screen pixels. The line will be rendered with a width of 10 screen pixels
}
}
]
}
interpolate
Creates interpolation of given values, based on another stop variable.
Available interpolation types are linear, step, cubic-bezier and exponential.
["interpolate", ["linear"], ["zoom"],
stop1, value1,
...
stopN, valueN,
]
["interpolate", ["step"], ["zoom"],
stop1, value1,
...
stopN, valueN,
]
["interpolate", ["cubic-bezier", x1, y1, x2, y2], ["zoom"],
stop1, value1,
...
stopN, valueN,
]
["interpolate", ["exponential", base], ["zoom"],
stop1, value1,
...
stopN, valueN,
]
Example
["zoom"] returns 9
["interpolate", ["linear"], ["zoom"], 8, 20, 10, 40] // returns 30
Math operators
["-", value, value]
["/", value, value]
["%", number, number]
["+", value, value]
["*", value, value]
"+" supported operands:
["+", boolean, boolean] // returns the OR of the two operands
["+", number, number]
["+", string, string] // returns the concatenated string
["+", vector2d, vector2d] // component-wise addition
["+", vector3d, vector3d] // component-wise addition
["+", vector3d, vector3d] // component-wise addition
["+", color, color] // returns the sum of the colors. The values are clamped to uint8
"-" supported operands:
["-", number, number]
["-", vector2d, vector2d] // component-wise subtraction
["-", vector3d, vector3d] // component-wise subtraction
["-", vector3d, vector3d] // component-wise subtraction
["-", color, color] // returns the difference of the colors. The values are clamped to uint8
"*" supported operands:
["*", boolean, boolean] // returns the AND of the two operands
["*", number, number]
["*", color, color] // component-wise multipication. Each color channel is interpreted as a value between 0 and 1 (128-> 0.5). Each channel values are multiplied and converted bach to uint8.
["*", color, number] // returns Color(color.r * number, color.g * number, color.b * number, color.a * number)
["*", number, color] // returns Color(color.r * number, color.g * number, color.b * number, color.a * number)
["*", vector2d, vector2d] // component-wise multiplication
["*", vector2d, number] // returns (vector2d.x * number, vector2d.y * number)
["*", number, vector2d] // returns (vector2d.x * number, vector2d.y * number)
["*", vector3d, vector3d] // component-wise multiplication
["*", vector3d, number] // returns (vector3d.x * number, vector3d.y * number, vector3d.z * number)
["*", number, vector3d] // returns (vector3d.x * number, vector3d.y * number, vector3d.z * number)
["*", vector4d, vector4d] // component-wise multiplication
["*", vector4d, number] // returns (vector4d.x * number, vector4d.y * number, vector4d.z * number, vector4d.z * number)
["*", number, vector4d] // returns (vector4d.x * number, vector4d.y * number, vector4d.z * number, vector4d.z * number)
"/" supported operands:
["/", number, number]
["/", vector2d, vector2d] // component-wise division
["/", vector3d, vector3d] // component-wise division
["/", vector4d, vector4d] // component-wise division
Updated yesterday