> ## Documentation Index
> Fetch the complete documentation index at: https://docs.here.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Style expressions reference for custom layers

* [Introduction](#introduction)
* [Query Expressions](#query-expressions)
* [Conditional Expressions](#conditional-expressions)
* [Comparison Expressions](#comparison-expressions)
* [Build Expressions](#build-expressions)
* [Conversion Expressions](#conversion-expressions)
* [Scale Expressions](#scale-expressions)
* [Math Expressions](#math-expressions)

## Introduction

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.

```javascript
[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.

```javascript
Example: null
```

#### boolean

The `boolean` type can only hold the values `true` or `false`.

```javascript
Example: true
```

#### number

The `number` type stores a real number.

```javascript
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.

```javascript
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.

```javascript
Example: "string_theory"
```

#### vector2d

The `vector2d` type stores a 2d vector of `numbers`. To create a `vector2d` value, use `make-vector` expression.

```javascript
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.

```javascript
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.

```javascript
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.

```javascript
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.

```javascript
Example: ["literal", {"a": 1, "b": 2}]
```

> #### Note
>
> Whenever an expression argument can be of more than one value type, we use `value` for that argument.

## Query expressions

### ref

References a value definition or an expression definition that can be evaluated to a value. Returns `null` if the definition cannot be found.

```javascript
["ref", string]
```

Example:

```javascript
"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.

```javascript
["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.

```javascript
{
    "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"

```javascript
["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.

```javascript
["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.

```javascript
{
    "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.

```javascript
["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.

```javascript
["!has", name]
["!has", name, dictionary]
```

The `!has` expression is equivalent to the negation of the `has` expression:

```javascript
["!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)`).

```javascript
["inside-range", input,
   range1Start, range1End,
   ...
   rangeNStart, rangeNEnd
]

["inside-range", input,
    ["literal", [range1Start, range1End, ... rangeNStart, rangeNEnd]]
]
```

Examples

```javascript
["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.

```javascript
["zoom"]
```

## Conditional expressions

### all

Returns `true` if all the sub expressions evaluate to `true`.

```javascript
["all", expression...] // boolean
```

Example:

```javascript
"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`.

```javascript
["any", expression...] // boolean
```

Example:

```javascript
"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`.

```javascript
["none", expression...]
```

Example:

```javascript
"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.

```javascript
["match",
  value,
  label1, result1,
  ...
  labelN, resultN,
  fallback
]
```

Example:

```javascript
"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.

```javascript
["case",
  condition1, result1,
  ...
  conditionN, resultN,
  fallback
]
```

Example:

```javascript
"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
```

## Comparison expressions

### `==`

Returns `true` if the values are equal. `boolean`, `number`, `string`, `vector2d`, `vector3d`, `vector4d`, `array` and `dictionary` types are supported.

```javascript
["==", value, value]
```

### `!=`

Returns `true` if the values are not equal. `boolean`, `number`, `string`, `vector2d`, `vector3d`, `vector4d`, `array` and `dictionary`  types are supported.

```javascript
["!=", value, value]
```

### `<`

Returns `true` if the first value is less than the second value. `boolean`, `number` and `string` types are supported.

```javascript
["<", value, value]
```

### `>`

Returns `true` if the first value is greater than the second value. `boolean`, `number` and `string` types are supported.

```javascript
[">", value, value]
```

### `<=`

Returns `true` if the first value is less than or equal to the second value. `boolean`, `number` and `string` types are supported.

```javascript
["<=", value, value]
```

### `>=`

Returns `true` if the first value is greater than or equal to the second value. `boolean`, `number` and `string` types are supported.

```javascript
[">=", value, value]
```

## Build expressions

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

```javascript
["rgb", number, number, number]
```

Example

```javascript
["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.

```javascript
["rgba", number, number, number, number]
```

Example

```javascript
["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

```javascript
["hsl", number, number, number]
```

Example

```javascript
["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

```javascript
["hsla", number, number, number, number]
```

Example

```javascript
["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`.

```javascript
["literal", json_document]
```

Example

```javascript
["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.

```javascript
["make-vector", number, number]
["make-vector", number, number, number]
["make-vector", number, number, number, number]
```

Examples:

```javascript
["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
```

## Conversion expressions

### !

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

```javascript
["!", value]
```

### to-color

Converts the `string` to `color`.

```javascript
["to-color", string]
```

Examples:

```javascript
["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
```

## Scale expressions

### pixel-world-scale

* visibility: public

Converts a number of screen pixels to world units(meters).

```javascript
["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.

```javascript
{
    "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
            }
        }
    ]
}
```

## Math expressions

### interpolate

Creates interpolation of given values, based on another stop variable.
Available interpolation types are `linear`, `step`, `cubic-bezier` and `exponential`.

```javascript
["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

```javascript
["zoom"] returns 9
["interpolate", ["linear"], ["zoom"], 8, 20, 10, 40] // returns 30
```

### Math operators

```javascript

["-", 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
```