Styling a Weather Map

Aside from choosing which mapping library to use for your weather map, you can also customize the styling of many of the data sources displayed on a map. Currently, markers, polygons, and polylines associated with a weather-related data source can contain custom styling.

Overriding Default Styles

A weather map instance is already configured with default styles for all point and shape data sources based on the standard categories and colors used within Xweather Raster Maps. However, you can override these groups and styles by setting your custom style provider object for a particular layer code on your weather map instance.

The easiest way to override the default styles is to include them in your map's configuration options at instantiation within a styles property, which should be an object containing style options keyed by layer code:

aeris.views().then((views) => {
    const map = new views.InteractiveMap('#map', {
        center: {
            lat: 38,
            lon: -120
        },
        zoom: 5,
        layers: 'earthquakes,drought-monitor',
        styles: {
            earthquakes: {
                marker: {
                    svg: {
                        shape: {
                            fill: {
                                color: '#ff0000'
                            },
                            stroke: {
                                color: '#ffffff',
                                width: 2
                            }
                        }
                    }
                }
            },
            'drought-monitor': {
                polygon: {
                    fill: {
                        color: '#c98b33'
                    },
                    stroke: {
                        color: '#ffffff',
                        width: 1
                    }
                }
            }
        }
    });
});

Interactive map with custom point and shape styles

Alternatively, you can set the styles when adding them to the map. Review the examples below for more information about styling various weather data sources.

Styling Raster/Tile Data

Raster layers can be styled using one of the many advanced image features available within Xweather Raster Maps, such as adding blend modes and filters (opens in a new tab).

To do so, provide an object of options as the second parameter to your weather map's addLayer method and include a styleproperty containing your style settings:

// add temperatures layer with water regions removed
map.addLayer('temperatures,water-flat:blend(dst-out)', {
    style: {
        opacity: 0.8,
        blur: 2
    }
});

Interactive map with custom raster layer styling

A raster style supports the following options:

OptionTypeDescription
opacitynumberOpacity of the layer on the map.
formatstringThe file extension format to use for Maps image requests (opens in a new tab). Default is png.
zIndexnumberThe z-index to apply to the layer when rendering on the map.
belowLayerstringString identifier under which the raster layer will be inserted. This is only available for third-party mapping libraries that support it (only Mapbox GL currently).
blurnumberAmount to blur the image.
blendModenumberBlend mode to apply to the image.

Refer to the RasterStyle type documentation for additional information regarding which style options are supported and their descriptions.

Styling Point Data

Weather-related markers can be represented on a weather map using a raster or SVG image, HTML, or a dynamically-rendered SVG circle, rectangle or custom path. By default all annotations are circular SVG shapes with both a fill and stroke color.

Similar to raster and tile data, point data sources are styled by providing a style.marker object in your options when adding a layer to the weather map. Depending on your desired outcome, you then need to provide an icon, html, or svg property on your style object which will be used for rendering it on the map.

A point/marker style supports the following options:

OptionTypeDescription
classNamestringStyle class name to add to the marker's DOM element when supported.
htmlstringHTML content to use when rendering the icon.
iconobjectProvides the icon options for the style. Refer to the Icon Markers section for the list of supported options.
svgobjectProvides the options for rendering the icon as an SVG element. Refer to the SVG Markers section for the list of supported options.
sizenumber[]Size of the icon as [width, height], e.g. [20, 15]
calloutfunctionxxxxx
skipbooleanIf true, then the marker(s) associated with the style will not be rendered to the map.

Refer to the MarkerStyle type documentation for additional information regarding which style options are supported and their descriptions.

Icon Markers

When using icon or image marker styles, you need to provide a URL to the image file for the marker at minimum within your style's icon property. This file can either be a raster image (PNG or JPEG), or it can be an SVG file. When using raster images for markers, you'll likely want to use a higher-resolution image for retina devices. So, also include an image URL to use for retina devices (when supported by the active mapping strategy).

An icon configuration supports the following options:

OptionTypeDescription
urlstringThe URL to the icon image (absolute or relative to the script path).
retinaUrlstringURL to a retina-sized version of the icon image. If not provided, the url icon path will be used for retina devices.
anchornumber[]The point coordinates of the tip of the icon (relative to the top-left corner) as [x, y], e.g. [-5, 0].

The following will use a standard and retina PNG for the marker's icon:

map.addLayer('fires', {
    style: {
        marker: {
            icon: {
                url: '/img/docs/js/map/marker-fire.png',
                retinaUrl: '/img/docs/js/map/marker-fire@2x.png'
            }
        }
    }
});

Or, you can provide SVG image files for your icons:

map.addLayer('fires', {
    style: {
        marker: {
            icon: {
                url: '/img/docs/js/map/marker-fire.svg'
            },
            size: [30, 30]
        }
    }
});

Interactive map with custom point layer styling using images

HTML Markers

If you want to render custom HTML inside your markers, you simply need to provide the html property on your style object with the HTML content string:

// marker is styled using the .marker-quake CSS selector
map.addLayer('earthquakes', {
    style: {
        marker: {
            html: '<div class="marker-quake">Quake</div>'
        }
    }
});

Then you can use CSS to further customize the styling of the content within the marker.

Interactive map with custom point layer styling with HTML

Note that your selected mapping strategy may or may not support custom HTML in a marker element. Refer to the documentation for your third-party mapping library to determine if HTML is supported in markers.

SVG Markers

The easiest and quickest method to customize weather markers on your map is to render them as SVG elements based on your options. You can configure your marker to render the SVG as a circle, rectangle, text, image, or custom SVG path. Then just provide the stroke, fill and/or text options.

An SVG configuration supports the following primary options where any or all options can be provided:

OptionTypeDescription
shapeobjectProvides the shape style configuration to display with the marker. See the supported shape options.
imageobjectProvides the image style configuration to display with for the marker. See the supported image options.
textobject or object[]Provides the text or series of text elements to display with the marker. See the supported text options.

SVG Shape Options

The following options are available when styling shapes to be used in an SVG marker:

OptionTypeDescription
typestringDetermines the type of shape to render. Supports circle, rect, or path. Default value is circle.
strokeobjectShape stroke style options.
stroke.colorstringStroke color.
stroke.opacitynumberStroke opacity.
stroke.widthnumberStroke width in pixels.
stroke.lineCapstringDefines the shape to be used at the end of the stroke. Supports butt, round, or square.
stroke.lineJoinstringDefines the shape to be used at the corners of the stroke. Supports miter, round, bevel, miter-clip, or arcs.
stroke.dashArraystringDefines the stroke dash pattern.
stroke.dashOffsetstringDefines the distance into the dash pattern to start the dash.
fillobjectShape fill style options.
fill.colorstringFill color.
fill.opacitynumberFill opacity.
fill.rulestringDefines how the inside of a shape is determined. Supports nonzero or evenodd.
smoothingstringAmount to simplify the shape path on each zoom level. More smoothing means better performance and a smoother appearance, where less means a more accurate representation. This option is not supported for all third-party mapping strategies.
pathstringDefines the shape of the path for SVG elements.
viewBoxstringDefines the position and dimension, in user space, of the SVG viewport. Only used when path is specified.
positionstring or { x: number, y: number }Position of the shape relative to the marker container. Supports an anchor string for relative positioning, or an { x, y } point for absolute positioning.
translate{ x: number, y: number }Position translation amount in the x and y axes.
transformstringDefines a list of transform definitions that are applied to the element.

SVG Image Options

The following options are available when styling images to be used in an SVG marker:

OptionTypeDescription
urlstringImage URL path.
sizenumber[]Size of the image as [width, height], e.g. [20, 15]
positionstring or { x: number, y: number }Position of the image relative to the marker container. Supports an anchor string for relative positioning, or an { x, y } point for absolute positioning.
translate{ x: number, y: number }Position translation amount in the x and y axes.
transformstringDefines a list of transform definitions that are applied to the element.

SVG Text Options

The following options are available when styling text to be used in an SVG marker:

OptionTypeDescription
valuenumber, stringText value to display.
anchorstart | middle | endDetermines the text container alignment relative to its position.
sizenumberFont size.
stylenumberFont style, e.g. normal or bold.
colorstringText color.
padding[x: number, y: number]Amount of padding to insert around the text, where x is the amount of horizontal padding and y is the amount of vertical padding.
autosizebooleanWhether to automatically size the marker based on the width and height of the text. Default is true.
positionstring or { x: number, y: number }Position of the image relative to the marker container. Supports an anchor string for relative positioning, or an { x, y } point for absolute positioning.
translate{ x: number, y: number }Position translation amount in the x and y axes.
transformstringDefines a list of transform definitions that are applied to the element.

The following style configuration will render markers as a 14x14 pixel circle with a yellow fill and white two pixel stroke:

map.addLayer('stormreports', {
    style: {
        marker: {
            svg: {
                shape: {
                    type: 'circle',
                    fill: {
                        color: '#ffcc00'
                    },
                    stroke: {
                        color: '#ffffff',
                        width: 2
                    }
                }
            },
            size: [14, 14]
        }
    }
});

Note that you also must provide a size value, which is an array containing the width and height values in pixels you want your marker to be rendered at. The above configuration would render a filled red circle with a 2px white stroke.

Interactive map with custom point layer styling using SVG

If you don't want a stroke or a fill, then simply leave those values out of your object:

map.addLayer('stormreports', {
    style: {
        marker: {
            svg: {
                shape: {
                    type: 'circle',
                    fill: {
                        color: '#7101df'
                    }
                }
            },
            size: [14, 14]
        }
    }
});

Maybe you want to use a rectangle instead of a square:

map.addLayer('stormreports', {
    style: {
        marker: {
            svg: {
                shape: {
                    type: 'rect',
                    fill: {
                        color: '#7101df'
                    },
                    stroke: {
                        color: '#ffffff',
                        width: 2
                    }
                }
            },
            size: [14, 14]
        }
    }
});

Interactive map with custom point layer styling using SVG rectangles

Alternatively, you can render SVG text for your marker by using the text property, which may require yo to adjust your size property to prevent the text from being cropped:

map.addLayer('stormreports', {
    style: {
        marker: {
            svg: {
                text: {
                    value: 'Cell',
                    color: '#ff0000',
                    size: 12,
                    style: 'bold'
                }
            },
            size: [50, 14]
        }
    }
});

Interactive map with custom point layer styling using text labels

You can also combine shapes and text to create a shield element for your markers, which is useful if you want to display text values over a colored background based on the data values. By default, each SVG element will be sized to fit the text within it, including any padding as defined by svg.text.padding:

map.addLayer('stormreports', {
    style: {
        marker: {
            svg: {
                shape: {
                    type: 'rect',
                    fill: {
                        color: '#7101df'
                    },
                    stroke: {
                        color: '#ffffff',
                        width: 2
                    },
                    radius: 3
                },
                text: {
                    value: 'Cell',
                    color: '#ffffff',
                    size: 12,
                    style: 'bold',
                    padding: [4, 2]
                }
            },
            size: [50, 14]
        }
    }
});

Interactive map with custom point layer styling using shapes and text labels

Custom SVG Paths

If you want even more customization options or provide more complex geometries for your markers, you can also provide a custom SVG path string to your style object. For instance, the following will render a red plus symbol for each storm report:

map.addLayer('stormreports', {
    style: {
        marker: {
            svg: {
                shape: {
                    type: 'path',
                    fill: {
                        color: '#ff0000'
                    },
                    path: 'M2 1 h1 v1 h1 v1 h-1 v1 h-1 v-1 h-1 v-1 h1 z'
                },
                viewBox: '0 0 5 5'
            },
            size: [20, 20]
        }
    }
});

Interactive map with custom point layer styling using custom SVG paths

Styling Shape Data

Styling shape data sources, such as polygons and polylines, can be done by providing the necessary stroke and fill style options when adding the layer to the map.

Similar to the other data source types, shape data sources are styled by providing style.polygon and/or style.polyline object(s) in your options when adding a layer to the weather map. Within this style object, simply provide the stroke and fill properties with your particular values. Note that only stroke options will be used for polyline styles:

map.addLayer('drought-monitor', {
    style: {
        polygon: {
            fill: {
                color: '#ff2400'
            },
            stroke: {
                color: '#ffffff',
                width: 1
            }
        }
    }
});

Interactive map with custom shape layer styling

Refer to the ShapeStyle type documentation for information regarding which style options are supported and their descriptions.

Data-Specific Styles

Oftentimes, point and shape data sources are rendered on the map differently based on specific values from the data they represent. For instance, earthquake markers would be rendered with different colors and sizes based on the magnitude values, or convective outlook polygons are rendered based on their category.

Up until now, we've been customizing data source styling using a static configuration, meaning all objects for that source will be rendered the same. Fortunately, the SDK also supports dynamic styling that allows you to return a style configuration based on the underlying model data that the object represents.

To use this feature, you'll need to provide a callback function block instead of a regular object for your style property which will receive the associated model data as an argument. Then, this function needs to return the style configuration to use for that object on the map. The style object can be any of the types supported by that data source type.

For example, the following is the default style configuration for storm cells, which are rendered based on their traits, such as hail, rotating or tornadic:

// dictionary that associates a color for each category
const colors = {
    default: '#000000',
    general: '#2ed300',
    hail: '#ebe100',
    rotating: '#f17200',
    tornado: '#ff2600'
};
 
map.addLayer('stormcells', {
    style: {
        marker: (data) => {
 
            // get the type property value from the passed in model data
            const { traits: { type }} = data;
 
            // return the style configuration for this storm cell marker
            return {
                svg: {
                    shape: {
                        type: 'circle',
                        fill: {
                            color: type ? colors[type.toLowerCase()] : colors.default
                        },
                        stroke: {
                            color: '#ffffff',
                            width: 2
                        }
                    }
                },
                size: [12, 12]
            };
        }
    }
});

Interactive map with custom point layer styling based on data values

You can see in this example each storm cell marker is filled using a color based on the cell's type code. We could take this a step further and use different sizes based on these codes as well by adding additional logic.

You can do something similar for shape data sources, such as convective outlooks:

// dictionary that associates a color for each category
const colors = {
    default: '#000000',
    general: '#b3e6b1',
    marginal: '#6cbd69',
    slight: '#f4f964',
    enhanced: '#e0b767',
    moderate: '#e0686a',
    high: '#fe59ff'
};
        
map.addLayer('convective-outlook', {
    style: {
        polygon: (data) => {
 
            // get the type property value from the passed in model data
            const { details: { risk: { type }}} = data;
 
            // return the style configuration for this storm cell marker
            return {
                fill: {
                    color: type ? colors[type.toLowerCase()] : colors.default,
                    opacity: 0.7
                }
            };
        }
    }
});