1

I have a polygon layer published in GeoServer through PostgreSQL (PostGIS) and I am trying to build a legend to use with GetLegendGraphich. The layer is requested as WMS layer in client with Leaflet on an Angular project.

My goal is to build a legend with properties 'fill' and 'fill-opacity' coming from the database (and not hard-coded in the style).

The layer is composed of following data:

  • id (Integer)
  • id_class (Integer)
  • fill_color (String). It is a hexadecimal color code.
  • fill_opacity (BigDecimal)
  • geom (MultiPolygon)

The primary key is {id, id_class}. 'id' is used as a filter:

SELECT id, id_class, fill_color, fill_opacity, geom
FROM table
WHERE id = %id%

So far, I am using fields 'fill_color' and 'fill_opacity' to set the symbology in the layer's SLD style (but without any legend). Like this:

  <NamedLayer>
    <Name>layer_name</Name>
    <UserStyle>
      <Title>layer_title</Title>
      <FeatureTypeStyle>
        
        <Rule>
          <Name>rule_name</Name>
          <Title>rule_title</Title>
          <PolygonSymbolizer>
             <Fill>
               <CssParameter name="fill-opacity">
                    <ogc:PropertyName>fill_opacity</ogc:PropertyName>
               </CssParameter>
               <CssParameter name="fill">
                   <ogc:PropertyName>fill_color</ogc:PropertyName>
               </CssParameter>
             </Fill>
             <Stroke>
                <CssParameter name="stroke">#000000</CssParameter>
                <CssParameter name="stroke-width">0.2</CssParameter>
             </Stroke>
          </PolygonSymbolizer>
        </Rule>

      </FeatureTypeStyle>
    </UserStyle>
  </NamedLayer>

My goal is to build a legend like this one:

My goal is to build a legend like this one:

enter image description here

which I have built using the following SLD style:

  <NamedLayer>
    <Name>layer_name</Name>
    <UserStyle>
      <Title>legend</Title>
      <FeatureTypeStyle>
        
        <Rule>
          <RasterSymbolizer>
            <ChannelSelection>
              <GrayChannel>
                <SourceChannelName>1</SourceChannelName>
              </GrayChannel>
            </ChannelSelection>
            <ColorMap type="values">
              <ColorMapEntry label=" [a - b]" quantity="1" color="#32ce80"/>
              <ColorMapEntry label=" (b - c]" quantity="2" color="#e3e926"/>
              <ColorMapEntry label=" (c - d]" quantity="3" color="#e8ad15"/>
              <ColorMapEntry label=" (d - e]" quantity="4" color="#ec0037"/>
              <ColorMapEntry label=" > e" quantity="5" color="#a0009d"/>
            </ColorMap>
          </RasterSymbolizer>
        </Rule>

      </FeatureTypeStyle>
    </UserStyle>
  </NamedLayer>

So, I could use the first one (which uses PolygonSymbolizer properly) for symbology and the latter for producing a legend image (which would be a hack).

However, I would like to have one style: color + opacity coming from data fields (not hard-coded), and the legend.

I tried to separate each 'id_class' into a different rule, but could not make it work. The fill colors are not used in the legend:

enter image description here

  <NamedLayer>
    <Name>layer_name</Name>
    <UserStyle>
      <Title>layer_title</Title>
      <FeatureTypeStyle>
        
        <Rule>
          <Name>class_1</Name>
          <Title>[a - b]</Title>          
          <ogc:Filter>              
              <ogc:PropertyIsEqualTo>
                  <ogc:PropertyName>id_class</ogc:PropertyName>
                  <ogc:Literal>1</ogc:Literal>                
               </ogc:PropertyIsEqualTo>                                
          </ogc:Filter>          
          <PolygonSymbolizer>
             <Fill>
               <CssParameter name="fill-opacity">
                    <ogc:PropertyName>fill_opacity</ogc:PropertyName>
               </CssParameter>
               <CssParameter name="fill">
                   <ogc:PropertyName>fill_color</ogc:PropertyName>
               </CssParameter>
             </Fill>
             <Stroke>
                <CssParameter name="stroke">#000000</CssParameter>
                <CssParameter name="stroke-width">0.2</CssParameter>
             </Stroke>
          </PolygonSymbolizer>
        </Rule>
        
        <Rule>
          <Name>class_2</Name>
          <Title>(b - c]</Title>          
          <ogc:Filter>              
              <ogc:PropertyIsEqualTo>
                  <ogc:PropertyName>id_class</ogc:PropertyName>
                  <ogc:Literal>2</ogc:Literal>                
               </ogc:PropertyIsEqualTo>                                
          </ogc:Filter>          
          <PolygonSymbolizer>
             <Fill>
               <CssParameter name="fill-opacity">
                    <ogc:PropertyName>fill_opacity</ogc:PropertyName>
               </CssParameter>
               <CssParameter name="fill">
                   <ogc:PropertyName>fill_color</ogc:PropertyName>
               </CssParameter>
             </Fill>
             <Stroke>
                <CssParameter name="stroke">#000000</CssParameter>
                <CssParameter name="stroke-width">0.2</CssParameter>
             </Stroke>
          </PolygonSymbolizer>
        </Rule>
       
        <Rule>
          <Name>class_3</Name>
          <Title>(c - d]</Title>          
          <ogc:Filter>              
              <ogc:PropertyIsEqualTo>
                  <ogc:PropertyName>id_class</ogc:PropertyName>
                  <ogc:Literal>3</ogc:Literal>                
               </ogc:PropertyIsEqualTo>                                
          </ogc:Filter>          
          <PolygonSymbolizer>
             <Fill>
               <CssParameter name="fill-opacity">
                    <ogc:PropertyName>fill_opacity</ogc:PropertyName>
               </CssParameter>
               <CssParameter name="fill">
                   <ogc:PropertyName>fill_color</ogc:PropertyName>
               </CssParameter>
             </Fill>
             <Stroke>
                <CssParameter name="stroke">#000000</CssParameter>
                <CssParameter name="stroke-width">0.2</CssParameter>
             </Stroke>
          </PolygonSymbolizer>
        </Rule>
        
        <Rule>
          <Name>class_4</Name>
          <Title>(d - e]</Title>          
          <ogc:Filter>              
              <ogc:PropertyIsEqualTo>
                  <ogc:PropertyName>id_class</ogc:PropertyName>
                  <ogc:Literal>4</ogc:Literal>                
               </ogc:PropertyIsEqualTo>                                
          </ogc:Filter>          
          <PolygonSymbolizer>
             <Fill>
               <CssParameter name="fill-opacity">
                    <ogc:PropertyName>fill_opacity</ogc:PropertyName>
               </CssParameter>
               <CssParameter name="fill">
                   <ogc:PropertyName>fill_color</ogc:PropertyName>
               </CssParameter>
             </Fill>
             <Stroke>
                <CssParameter name="stroke">#000000</CssParameter>
                <CssParameter name="stroke-width">0.2</CssParameter>
             </Stroke>
          </PolygonSymbolizer>
        </Rule>        

        <Rule>
          <Name>class_5</Name>
          <Title>> e</Title>          
          <ogc:Filter>              
              <ogc:PropertyIsEqualTo>
                  <ogc:PropertyName>id_class</ogc:PropertyName>
                  <ogc:Literal>5</ogc:Literal>                
               </ogc:PropertyIsEqualTo>                                
          </ogc:Filter>          
          <PolygonSymbolizer>
             <Fill>
               <CssParameter name="fill-opacity">
                    <ogc:PropertyName>fill_opacity</ogc:PropertyName>
               </CssParameter>
               <CssParameter name="fill">
                   <ogc:PropertyName>fill_color</ogc:PropertyName>
               </CssParameter>
             </Fill>
             <Stroke>
                <CssParameter name="stroke">#000000</CssParameter>
                <CssParameter name="stroke-width">0.2</CssParameter>
             </Stroke>
          </PolygonSymbolizer>
        </Rule>        
      
      </FeatureTypeStyle>
    </UserStyle>
  </NamedLayer>

https://my_server/geoserver/wms?REQUEST=GetLegendGraphic&VERSION=1.0.0&FORMAT=image/png&LAYER=my_layer

Is there a way or I must use hard-coded fill color values?

4
  • You can create a PNG of the required legend graphic and add that to the layer.
    – Ian Turton
    Mar 8 at 13:39
  • Tks Ian. The whole point is to change the hex color code directly in the database and have symbology and legend altered. Would your suggestion work like that? Mar 8 at 13:46
  • Then GeoServer would need to read the entire table for each legend display
    – Ian Turton
    Mar 8 at 18:57
  • For each id (used in the filter) there are up to five features (rows) (one for each 'id_class'). Would that be a problem? Mar 8 at 19:12

1 Answer 1

0

You can prepare a style with sections that are meant just legend production, and section just for rendering (or for both). See here:

https://docs.geoserver.org/stable/en/user/styling/sld/extensions/rendering-selection.html#rendering-selection

2
  • Sorry, I completely missed your answer at the time. I got the following error: line : cvc-complex-type.2.4.d: Invalid content was found starting with element 'VendorOption'. No child element is expected at this point.. Used the vendor option after </Stroke> and before </PolygonSymbolizer> in the first SLD example of my question. Also, I got it how I could use this in the map part, but I did not understand how I could build the legend getting the colors from my layer field. Could you expand your answer to include an example? Thanks. May 9 at 15:56
  • 1
    Don't stop at the validation results (it's a formal check only) and try to actually save and use the style. May 10 at 7:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.