A legend for your SLD map

By adding a legend to your map, you can improve user experience. In a legend, you use simple images and descriptions to explain what the map shows.

LegendPanel
Figure 1. Legend panel in the LuciadRIA Symbology Encoding sample

Creating entries for your legend

Legend entries can be regular Features resembling the features on your map, one for each type of visualisation. You can create any feature with properties to trigger the right SLD style for the visualization type.

Program: Create a legend feature for big cities
import {Feature} from "@luciad/ria/model/feature/Feature.js";
import {createPoint} from "@luciad/ria/shape/ShapeFactory.js";
import {getReference} from "@luciad/ria/reference/ReferenceProvider.js";

const pointShape = createPoint(getReference("CRS:84"), [0, 0]);
const cityLegendFeature = new Feature(pointShape, {SCALERANK: 1, NAME: "LA"}, 0);

However, the style as defined in your SLD file for regular map features might not lead to an optimal legend preview. Legend icons might be too small or too big, text might become unreadable, world-sized styling might lead to unexpected images.

For the cityLegendFeature defined in Program: Create a legend feature for big cities , that could lead to the image in Figure 2, “world-sized icon in a legend”. What happened here is that the world-sized styling defined for these large cities is applied to the legend icon as well, making the icon too big for the legend image.

LegendEntryWrong
Figure 2. world-sized icon in a legend

To fix this issue of non-appropriate legend styling, you must combine two mechanisms. First, you define legend-specific styling in your SLD files using the vendor option 'inclusion'. Next, you must create a dedicated painter for legend entries.

Defining legend-specific SLD styling with vendor option 'inclusion'

You can use the vendor option inclusion to differentiate between styling on a regular map and styling for a legend. It defines whether LuciadRIA uses a particular element Rule, FeatureTypeStyle or Symbolizer when it generates either map output or legend output.

This vendor option allows you to generate appropriate legend images, either by setting a pre-defined image for use in the legend, or by changing the style to skip complexity, labeling, and replace world-sized styling — a key benefit when you’re using the LuciadRIA LegendPanel.

To set the inclusion vendor option, add this to the appropriate style element in your SLD file:

<VendorOption name="inclusion">legendOnly</VendorOption>

Valid values are:

  • legendOnly: skip the style element when painting on a regular map. To use these legend styles, you must create a special painter for legend entries, the regular Symbology Encoding painter skips these styles.

  • mapOnly: skip the style element when painting legends. The regular Symbology Encoding painter uses these styles.

  • normal: use the style element for both map and legend painting. The regular Symbology Encoding painter uses these styles.

    The normal value has the same effect as omitting the vendor option.

Example using a pre-defined image

In SLD Rule for 'large cities - zoomed in', you can see that the rule for "Large cities - zoomed in" contains a world-sized point symbolizer and a world-sized text symbolizer. They could lead to the incorrectly sized legend icon in Figure 2, “world-sized icon in a legend”. However, in this SLD, both symbolizers are marked as mapOnly. Next to them, there is another legendOnly point symbolizer, merely pointing to a pre-defined image for the legend entry as shown in this figure.

LargeCity2SLDLegend
Figure 3. pre-defined image as legend entry

Expand for the code to create the "Large city" legend:

<?xml version='1.0' encoding='UTF-8'?>
<FeatureTypeStyle xmlns="http://www.opengis.net/se"
                  xmlns:ogc="http://www.opengis.net/ogc"
                  xmlns:gml="http://www.opengis.net/gml"
                  xmlns:xlink="http://www.w3.org/1999/xlink"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://www.opengis.net/ogc
                   http://schemas.opengis.net/filter/1.1.0/filter.xsd
                   http://www.opengis.net/se
                   http://schemas.opengis.net/se/1.1.0/FeatureStyle.xsd
                   http://www.w3.org/1999/xlink
                   http://www.w3.org/1999/xlink.xsd "
                  version="1.1.0">
  <Description>
    <Title>Populated places</Title>
  </Description>
  <Rule>
    <Description>
      <Title>Large cities - zoomed in</Title>
    </Description>
    <MaxScaleDenominator>6.0E5</MaxScaleDenominator>
    <ogc:Filter>
      <ogc:PropertyIsBetween>
        <ogc:PropertyName>SCALERANK</ogc:PropertyName>
        <ogc:LowerBoundary>
          <ogc:Literal>1</ogc:Literal>
        </ogc:LowerBoundary>
        <ogc:UpperBoundary>
          <ogc:Literal>2</ogc:Literal>
        </ogc:UpperBoundary>
      </ogc:PropertyIsBetween>
    </ogc:Filter>
    <PointSymbolizer>
      <Graphic>
        <ExternalGraphic>
          <OnlineResource xlink:href="/sampledata/img/LargeCity2SLDLegend.png"/>
          <Format>image/png</Format>
        </ExternalGraphic>
        <Size>45</Size>
      </Graphic>
      <VendorOption name="inclusion">legendOnly</VendorOption>
    </PointSymbolizer>
    <PointSymbolizer uom="http://www.opengeospatial.org/se/units/metre">
      <Graphic>
        <ExternalGraphic>
          <InlineContent encoding="base64">
            iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAH0lEQVQYV2P8DwQMeAAjSEEdIyNWJU1AvUNHAT5vAgDR8jHptuzwOwAAAABJRU5ErkJggg==
          </InlineContent>
          <Format>image/png</Format>
        </ExternalGraphic>
        <Size>
          2800
        </Size>
        <Opacity>0.6</Opacity>
        <Rotation>45</Rotation>
      </Graphic>
      <VendorOption name="inclusion">mapOnly</VendorOption>
    </PointSymbolizer>
    <TextSymbolizer uom="http://www.opengeospatial.org/se/units/metre">
      <Label>
        <ogc:PropertyName>NAME</ogc:PropertyName>
      </Label>
      <LabelPlacement>
        <PointPlacement>
          <Displacement>
            <DisplacementX>0</DisplacementX>
            <DisplacementY>2500</DisplacementY>
          </Displacement>
        </PointPlacement>
      </LabelPlacement>
      <Font>
        <SvgParameter name="font-family">Tahoma</SvgParameter>
        <SvgParameter name="font-weight">bold</SvgParameter>
        <SvgParameter name="font-size">1800</SvgParameter>
      </Font>
      <Halo>
        <Radius>150</Radius>
        <Fill>
          <SvgParameter name="fill">#dddddd</SvgParameter>
        </Fill>
      </Halo>
      <Fill>
        <SvgParameter name="fill">#111111</SvgParameter>
      </Fill>
      <VendorOption name="inclusion">mapOnly</VendorOption>
    </TextSymbolizer>
  </Rule>
</FeatureTypeStyle>

Example using altered styling

In SLD FeatureTypeStyle for 'US rail roads', you can see two rules containing world-sized line symbolizers, marked mapOnly. They have appropriate pixel-sized counterparts, marked legendOnly. They make sure that the legend entry for the railroad has a nice railroad style.

Expand for the code to create the "Railroad" legend:

<?xml version='1.0' encoding='UTF-8'?>
<FeatureTypeStyle xmlns="http://www.opengis.net/se" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://www.opengis.net/se http://schemas.opengis.net/se/1.1.0/FeatureStyle.xsd"
                  version="1.1.0">
  <Description>
    <Title>US rail roads</Title>
  </Description>
  <Rule>
    <MaxScaleDenominator>2.0E4</MaxScaleDenominator>
    <LineSymbolizer uom="http://www.opengeospatial.org/se/units/metre">
      <Stroke>
        <SvgParameter name="stroke">#333333</SvgParameter>
        <SvgParameter name="stroke-width">4</SvgParameter>
      </Stroke>
      <VendorOption name="inclusion">mapOnly</VendorOption>
    </LineSymbolizer>
    <LineSymbolizer>
      <Stroke>
        <SvgParameter name="stroke">#333333</SvgParameter>
        <SvgParameter name="stroke-width">8</SvgParameter>
      </Stroke>
      <VendorOption name="inclusion">legendOnly</VendorOption>
    </LineSymbolizer>
  </Rule>
  <Rule>
    <MaxScaleDenominator>2.0E4</MaxScaleDenominator>
    <LineSymbolizer uom="http://www.opengeospatial.org/se/units/metre">
      <Stroke>
        <SvgParameter name="stroke">#ffffff</SvgParameter>
        <SvgParameter name="stroke-width">3</SvgParameter>
        <SvgParameter name="stroke-dasharray">7 7</SvgParameter>
      </Stroke>
      <VendorOption name="inclusion">mapOnly</VendorOption>
    </LineSymbolizer>
    <LineSymbolizer>
      <Stroke>
        <SvgParameter name="stroke">#ffffff</SvgParameter>
        <SvgParameter name="stroke-width">5</SvgParameter>
        <SvgParameter name="stroke-dasharray">10 10</SvgParameter>
      </Stroke>
      <VendorOption name="inclusion">legendOnly</VendorOption>
    </LineSymbolizer>
  </Rule>
</FeatureTypeStyle>

Creating a painter for legend entries

The regular painter for symbology encoding renders for the map, ignoring all styling flagged with the vendor option inclusion set to legendOnly. If you want to render for the legend, you must create the painter with an explicit painterType set to legend.

Program: creating a legend painter demonstrates how to create a painter that uses only legend styles and normal styles, and ignores map styles. Thus, this painter ignores all styling flagged with the vendor option inclusion set to mapOnly.

Program: creating a legend painter (from samples/symbologyencoding/SampleLayer.ts)
const legendPainter = await createPainterFromString(seSource, {
  strict: true,
  functionEvaluators: roadFunctionEvaluators,
  painterType: "legend",
});

LegendPanel and Legend Toolbox

To create a LegendPanel as shown in Figure 1, “Legend panel in the LuciadRIA Symbology Encoding sample”, you can use the LegendPanel available in the LuciadRIA samples. See samples/common/ui/overlay/LegendPanel.tsx in your LuciadRIA distribution. You can also make use of the Legend tools in the LuciadRIA Toolbox. See the toolbox/ria/legend directory. These legend tools allow you to create nice-looking, dynamic legends for a map with one or more feature layers.