# Style guide for custom layers Customize at runtime the visual appearance of [predefined schemes](map-schemes.md) and of custom [raster](custom-map-styles.md#add-custom-raster-layers), [line](custom-map-styles.md#add-custom-line-layers), [polygon](custom-map-styles.md#add-custom-polygon-layers) or [point](custom-map-styles.md#add-custom-point-layers) layers through the use of custom [styles](custom-map-styles-style-guide.md#style), which can be controlled through a series of APIs along with a JSON-based `Style` description. > #### Note > > This is a beta release of this feature, so there could be a few bugs and unexpected behaviors. Related APIs may change for new releases without a deprecation process. A `Style` is an abstraction of a custom layer style: * Use the `JsonStyleFactory` to create a `Style` from JSON strings. * Use the `MapLayerBuilder.withStyle(Style)` method to provide a custom style when creating a `MapLayer`. * Use the `MapLayer.setStyle(Style)` method to update a custom layer style at runtime. The JSON style syntax is described in greater detail below. With the HERE SDK, follow the below steps to customize the visual appearance of a custom layer: * Create a JSON style string for your custom layers using an appropriate technique. > using the `raster` technique as described in the [style techniques reference](custom-map-styles-style-techniques.md) for a custom raster layer. ```java private final static String MY_CUSTOM_LAYER_STYLE = "{\n" + " \"styles\": [\n" + " {\n" + " \"layer\": \"my custom layer\",\n" + " \"technique\": \"raster\",\n" + " \"attr\": {\n" + " \"opacity\": 1.0\n" + " }\n" + " }\n" + " ]\n" + "}"; ``` > using the `line` technique as described in the [style techniques reference](custom-map-styles-style-techniques.md) for a custom line layer. ```java private final static String MY_CUSTOM_LAYER_STYLE = "{\n" + " \"styles\": [\n" + " {\n" + " \"layer\": \"my custom layer\",\n" + " \"technique\": \"line\",\n" + " \"attr\": {\n" + " \"width\": 5.0,\n" + " \"color\": \"#ff0000ff\"\n" + " }\n" + " }\n" + " ]\n" + "}"; ``` * Use `JsonStyleFactory` to create a custom `Style` out of the style string. ```java Style layerStyle = JsonStyleFactory.createFromString(MY_CUSTOM_LAYER_STYLE); ``` * Create the custom layer using the newly created `Style` ```java MapLayer mapLayer = new MapLayerBuilder() ... .withName("my custom layer") .withStyle(layerStyle) .build(); ``` * Or assign the newly created `Style` to an existing custom layer. ```java myCustomLayer.setStyle(layerStyle); ``` ## Style Style defines the visual appearance of rendered objects. It does so by providing information about the rendering technique and the technique parameters for every object. Style is defined in a JSON file with a schema described in the following sections. ## Style rule The top-level key `styles` contains the style description. The value of `styles` is an array of style rules. Conceptually, each style rule represents a separate draw invocation - two style rules within a layer mean that the layer features are drawn twice. ### layer Each style rule is associated with a layer through the `layer` key. A single layer can be associated with multiple style rules. In the following style, `layer1` has two style rules: ```javascript { "styles" : [ // first style rule: { "layer": "layer1" ... }, // second style rule: { "layer": "layer1" ... }, ] } ``` > #### Note > > Style rules inside `styles` can be arranged in any order. ### when Style Rule applies to an object only if `when` filter is true for that object. The `when` is optional and if not specified it is always true. In order to distinguish among objects, `when` expression uses object data attributes. A data attribute is a name-value pair attached to an object. Objects can have an arbitrary number of data attributes. The Style system itself does not have any inherent expectations about the presence of certain data attributes. Writing a style for particular data source however heavily depends on data scheme. Example below contains `when` in Style Rule: ```javascript { "styles" : [ { "layer": "layer1" "when": ["==", ["get", "kind"], "a special kind"] ... } ] } ``` The `when` value is a boolean [expression](custom-map-styles-style-expressions.md) comparing object data attribute named `kind` against a string constant `a special kind`. ### technique Every style rule must specify a `technique`. The `technique` defines how the object's geometry is transformed into a renderable object and how it is rendered - which shader is used and what uniforms are set. In addition to `technique` name, the rule can also provide a set of technique attribute values under the `attr` key. ```javascript { "styles": [ { "layer": "layer1", "technique": "raster", "attr": { "opacity": 0.5 } } ] } ``` The example above has a `technique` set to `raster` and a single technique attribute `opacity` set to 0.5. See [style techniques reference](custom-map-styles-style-techniques.md) for a complete list of available techniques and their attributes. ## Expressions Expressions define value of `when` filter and technique `attribute values`. Expression is represented in JSON as an `array` whereas first argument is an expression `name`, and the rest of the entries are expression arguments. Arguments are in most cases also expressions. ```javascript [name, argument1, ...argumentN] ``` Example: `1+2` is written as `["+", 1, 2]` See [Expression Reference](custom-map-styles-style-expressions.md). ## Definitions Expressions which are used often can be defined once in `definitions` and then referenced in any expression, by using `["ref", name]` expression. ```javascript { "definitions": { "definition1": "#ff0000", "definition2": ["ref", "definition1"] // Definition value is also an expression ], "styles": [ { "layer": "layer1", "technique": "line", "attr": { "color": ["ref", "definition2"] // "#ff0000" } }, } } ``` ## Customize map schemes with the Style class With the [HERE Style Editor](map-style-editor.md), you can create custom map schemes. At runtime, you can modify both your custom schemes and the predefined `MapScheme` styles. For example, you might increase the font size of all labels based on user preferences. In addition, you can customize the visual appearance of raster, line, polygon, and point layers. All `MapScheme` styles are supported. ```java Java private final static String MY_STYLE_CUSTOMIZATION = "{\n" + " \"definitions\": {\n" + " \"General.Labels.Scale.Factor\": 1.5 + " }\n" + "}"; Style styleUpdate = JsonStyleFactory.createFromString(MY_STYLE_CUSTOMIZATION); mapView.getHereMap().getStyle().update(styleUpdate); ``` ```kotlin Kotlin private val MY_STYLE_CUSTOMIZATION: String = ("""{ "definitions": { """ + " \"General.Labels.Scale.Factor\": 1.5 + " }\n" + "}") val styleUpdate: Style = JsonStyleFactory.createFromString(MY_STYLE_CUSTOMIZATION) mapView!!.hereMap.style.update(styleUpdate) ``` The following style customizations are supported for predefined map styles: * `General.Labels.Scale.Factor`: a factor used to scale map labels (icons and text). The default value is 1. Values less than 1 would down-scale map labels and values larger than 1 would up-scale map labels. Values less than 0 or very large values are not supported and lead to undefined behavior. A `null` value restores the default.