Layers Panel

An interactive map application contains a layers panel component, which is fully configurable and allows the user to toggle your desired layers on and off as well as filter a layer's vector data currently visible on the map.

Example layers panel

Configuration

The following options are supported when configuring your InteractiveMapApp instance:

OptionTypeDescriptionDefault
buttonsarrayAn array of button elements to render in the panel, where each button controls a single layer or layer group. Refer to the Button Configuration section below for more information.
titlestringLabel title for the panel. The title is only rendered if the panel is toggleable and in the expanded state.
classNamestringA CSS class name to add to the panel, which can be used for additional style customizations.
toggleablebooleanA boolean value indicating whether the panel is toggleable. A toggleable panel will display a button in the closed/collapsed state initially. Clicking on the button will expand the panel to its full size.false
iconstringIcon HTML to display in the button when the panel is collapsed. This value can be any valid HTML, including an <img> or <svg> element.
positionobjectOptions to configure the position of the panel within its parent container.
position.pinstringThe position to pin the panel to relative to its parent container. Supports topleft, top, topright, left, center, right, bottomleft, bottom, or bottomleft.
position.translateIPointAmount to translate the panel in the x and y axis relative to its pinned position.{ x: 0, y: 0 }

Button Configuration

OptionTypeDescriptionDefault
titlestringButton label title.
valuestring | numberValue associated with the button, which is the either the map layer/source key or group key if it's a segmented button.
optionsobjectOptional custom data associated with the button. This is often used to store request parameters to be used when requesting map data associated with the button.
segmentsarrayAn array of button configurations to be rendered as segment options for this button. These segments are usually associated with the parent button and are used to toggle between values or apply one or more filters to the button's value. Segments can only be defined for buttons at the root level, not for buttons defined as segments.
filterbooleanA boolean value indicating whether the button segments should function as filter options to the parent button instead of toggling between values.false
multiselectbooleanA boolean value indicating whether multiple child buttons or segments can be selected.
buttonsarrayAn array of button configurations to display as a group. The group will be rendered with a group title indicated by this object's title property.
controlsobjectOptional configuration for additional controls rendered with the button, such as a close indicator on hover, layer settings popover, etc. See Button Controls below for more information.

Default Configuration

The following is the default configuration object for a InteractiveMapApp instance:

{
    buttons: undefined
}

Your implementation is responsible for declaring the series of button options to render within the panel.

Also review the default configuration for an InteractiveMapApp instance that is applied to its internal layers panel.

Segmented Buttons

Each button in the layers panel can define a series of segments for that button, which act as related values pertaining to the button or a series of filters that can be applied to the button's value. When a segment is selected, the button will trigger a value:change with information about the button.

Segments as Values

When you set a button's filter configuration option to false, which is the default, then each segment within the button acts as its own value and only one segment can be selected at a time.

For instance, you want to group all satellite layer options into a single button while still allowing the user to toggle between the different types of satellite imagery. You would set this button up using the following configuration:

{
    id: 'satellite',
    title: 'Satellite',
    segments: [{
        value: 'satellite:75',
        title: 'Infrared'
    },{
        value: 'satellite-infrared-color:75',
        title: 'Color Infrared'
    },{
        value: 'satellite-visible:75',
        title: 'Visible'
    },{
        value: 'satellite-geocolor',
        title: 'Geocolor'
    },{
        value: 'satellite-water-vapor:75',
        title: 'Water Vapor'
    }],
    options: {
        style: {
            zIndex: 0
        }
    }
}

Using the above configuration, when the user first selects the Satellite button, the first segment is selected and the satellite layer is added to the map if a previous value has not already been set. Selecting one of the other segments will remove the previous satellite-related layer and add the selected one, toggling between the different satellite types.

In the above configuration, options are also provided, which are the layer options to use when adding one of the layers to the interactive map. Setting the zIndex to 0 will ensure that any satellite layer will be inserted below all other layers, such as radar or alerts.

Segments as Filters

Instead of having button segments toggle between a series of different values, you can set your button's filter configuration option to true to have the segments function as filters to the button's main value. This is useful for vector map content sources, such as markers or polygons. Additionally, if you set multiselect to true on your button, then multiple segments can be selected at once, meaning multiple filters can be applied to the button's source at a given time.

For example, you may want to allow the user to filter storm reports by category. You'd then define each category as its own segment in your main storm reports button:

{
    id: 'stormreports',
    value: 'stormreports',
    title: 'Storm Reports',
    filter: true,
    multiselect: true,
    segments: [{
        value: 'all',
        title: 'All'
    },{
        value: 'rain,flood',
        title: 'Rain/Flood'
    },{
        value: 'wind',
        title: 'Wind'
    },{
        value: 'snow',
        title: 'Snow'
    },{
        value: 'hail',
        title: 'Hail'
    }]
}

With the above configuration, the button's main value corresponds to the layer or map content source key to use. By default, the segment whose value is all will be selected initially. Then when the user selects one or more of the other segments, the filter value are used to update the map content source's data on the map. Since multiselect is enabled, each segment acts as a toggle to enable and disable the filter from the request.

If you have a segment with value of all in your segments, selecting that segment will deselect all other selected segments so that all filters are removed from the map content source's data request.

Grouped Segments

You can also group related segments together into individual segments groups and have multiple segment groups for a single button. This is useful in use cases where you may have multiple filters you want to enable for a vector data source where each segment group controls the active filter for a specific property.

To create grouped segments for your button, you'll need to provide an object on your button's segments option that contains a groups property. Then, set up your segment groups as an array of configuration objects similar to an array of segmented button options. For instance, the following configuration would define an Observations layer control set up with two filters as segment groups: data property and station type:

{
    value: 'obs-point',
    title: 'Observations',
    filter: true,
    segments: {
        groups: [{
            id: 'fields',
            title: 'Property',
            segments: [{
                value: 'tempF',
                title: 'Temperatures'
            },{
                value: 'windSpeedMPH',
                title: 'Winds'
            },{
                value: 'humidity',
                title: 'Humidity'
            },{
                value: 'precipIN',
                title: 'Precipitation'
            },{
                value: 'sky',
                title: 'Sky Cover'
            },{
                value: 'uvi',
                title: 'UV Index'
            }]
        },{
            id: 'filter',
            title: 'Station Type',
            segments: [{
                value: 'allstations',
                title: 'All'
            },{
                value: 'metar',
                title: 'METAR'
            },{
                value: 'madis',
                title: 'MADIS'
            },{
                value: 'pws',
                title: 'PWS'
            }]
        }]
    }
}

Now, the layer's data will be updated based on the selected filter option from each segment group.

Button Groups

You can group related buttons within the layers panel so that groups of similar layers can be represented as a single collection visually. Creating a button group is simple as well. Simply create a nested buttons array within your parent button item's configuration.

The following would create an “Observations” group consisting of a variety of radar, satellite and observation layers:

{
    title: 'Observtions',
    buttons: [{
        id: 'radar',
        value: 'radar:80',
        title: 'Radar'
    },{
        id: 'satellite',
        title: 'Satellite',
        segments: [{
            value: 'satellite:75',
            title: 'Infrared'
        },{
            value: 'satellite-visible:75',
            title: 'Visible'
        },{
            value: 'satellite-geocolor,states-outlines-dk',
            title: 'Geocolor'
        }],
        options: {
            style: {
                zIndex: 0
            }
        }
    },{
        title: 'Surface',
        value: 'surface-analysis'
    },{
        title: 'Temperatures',
        value: 'temperatures:75,states-outlines-dk,temperatures-text'
    },{
        title: 'Winds',
        value: 'wind-speeds:75,states-outlines-dk,wind-dir,wind-speeds-text'
    },{
        title: 'Humidity',
        value: 'humidity:75,states-outlines-dk,humidity-text'
    },{
        id: 'visibility',
        title: 'Visibility',
        value: 'fvisibility'
    },{
        title: 'Air Quality',
        value: 'air-quality'
    }]
}

Button Controls

Button controls allow you to add additional functionality to a button instance. For instance, a close/remove icon can appear on hover indicating that clicking the currently selected button will remove that layer from the map. Or, you can display layer-specific options in a popover by configuring a settings control for the button. For instance, you would use this settings control to configure an opacity slider that enables real-time opacity changes for a specific layer on the map.

The following button control options are currently supported:

OptionTypeDescriptionDefault
closebooleanWhen enabled, displays a close/remove icon when a selected button is moused over. This indicates that clicking the button will deselect it and remove the associated layer from the map.true
activitybooleanWhen enabled, an activity indicator will appear on the button when the associated layer is actively requesting data for the map. This is currently only for vector layers, not tile/raster layers.true
settingsarrayDefines an array of options and controls to display in a popover component next to the button, allowing the user to adjust various settings for the associated layer (such as opacity). If settings are provided, a settings (gear) icon will be rendered on the button when in the selected state to present the settings popover when clicked. See the Setting Control Types section below for the list of supported control types you can use.

Setting Control Types

TypeDescription
sliderSupports setting a value within a min and max value range using a slider control.
opacityA built-in and properly configured slider control for adjusting an opacity value whose value ranges from 0 (0%) to 1 (100%).

Receiving Control Events

If you are setting up a custom settings control for your buttons instead of one of the built-in ones, you will often want to be notified when those control values change. These events will be propagated up to your InteractiveMapApp instance where you can set up an event handler for the layer:change:control event:

app.on('layer:change:control', (e) => {
    console.log('layer control changed', e.data);
});

The event's data object will contain information about the control that triggered the event as well as the id and value of the button from which the change occurred.

Adding a Layer Opacity Slider

When working with raster/tile layers, you'll often want to be able to adjust the layer's opacity in order for underlying map features and layers to be partially visible. You can set the initial layer opacity by defining a custom raster layer style with your layer. However, you may want to allow the user to adjust the opacity afterwards from the map application interface.

Using the button controls configuration as outlined above, specifically the settings option and built-in opacity control, you can effortlessly add this functionality to your applications. You can also define the default opacity value to use for the layer and control by defining the necessary raster style configuration options:

{
    title: 'Radar',
    value: 'radar',
    options: {
        style: {
            opacity: 0.5
        }
    },
    controls: {
        settings: [{
            type: 'opacity'
        }]
    }
}

These same controls can be used for segmented button groups, in which case the opacity value in the control will be used for all raster layers within the group:

{
    id: 'radar-type',
    title: 'Radar',
    segments: [{
        title: 'Radar',
        value: 'radar'
    },{
        title: 'Global Radar',
        value: 'radar-est'
    }],
    options: {
        style: {
            opacity: 0.5
        }
    },
    controls: {
        settings: [{
            type: 'opacity'
        }]
    }
}

When using this built-in opacity control, the layer opacity adjustments are automatically handled by the SDK. So you do not need to set up an event handler for the layer:change:control event on your InteractiveMapApp instance.

Adding and Removing Buttons

Buttons can be added and removed at runtime after the layers panel has been rendered. This is useful for extending the map application to provide custom functionality, such as the ability to toggle between base map styles.

The layers panel provides the following methods for managing its buttons:

MethodDescription
add(:config, :events)Adds a new button to the end of the set using the provided button configuration. If :events is true, then the default button events will be added to the button, which will trigger select and deselect events when the button is toggled (default is true).
insertAt(:index, :config, :events)Similar to add(), but instead will insert a new button at a specific index in the array of buttons using the provided button configuration.
removeAt(:index)Removes the button at the specified index.
removeForId(:id)Removes the button that matches the specified identifier.

See the custom layer buttons example for a sample use-case where these methods can be used.