SLD styling for online mapping libraries
A javascript package that aims to bring styling from a sld document to popular mapping tools. The project consists of two parts:
The OpenLayers style converter tries to be as efficient as possible by recycling OpenLayers Style instances whenever possible.
CONTRIBUTIONS WELCOME!
More information about the standards:
See docs/examples folder, to serve them locally
npm start
The SLDReader library can read both SLD v1.0 and SLD v1.1 documents, but not every part of the SLD standard is (or can be) implemented by the SLDReader and OpenLayers style converter (yet).
Marks with well known symbol names are supported: circle, square, triangle, star, cross, x, hexagon, octagon. ExternalGraphic icons are supported.
Two custom marks are also supported: horline
for a horizontal line through the center and backslash
for a line from the top left to the bottom right. Use backslash instead of horline if you want to have diagonal hashing as a polygon graphic fill.
Wellknown names that reference a symbol library, like ttf://CustomFont#42
are not supported. The Size and Rotation elements may be dynamic by using the PropertyName element.
Only one Graphic per PointSymbolizer is supported. Each Graphic can only have one Mark or one ExternalGraphic.
Only these svg-parameters are supported:
GraphicStroke with Mark or ExternalGraphic is mostly supported.
GraphicFill and PerpendicularOffset are not supported.
ExternalGraphic is mostly supported with these caveats:
stroke-dasharray
parameter to add a gap between stroke marks. To do this, use a dash array with two parameters: the first parameter being the size of the graphic and the second being the gap size. See the " GraphicStroke: ExternalGraphic" example.The following QGIS vendor options are supported on line symbolizers with a graphic stroke:
<VendorOption name="placement">firstPoint</VendorOption>
<VendorOption name="placement">lastPoint</VendorOption>
See the demo page for an example.
Polygons with static fill and stroke style parameters are supported. See LineSymbolizer above for supported properties for the polygon outline.
For polygon graphic fills, both ExternalGraphic and Mark graphic fills are supported. The Marks supported here are the same as for a point symbolizer, with the additional restriction that feature-dependent value cannot be used.
The following WellKnownNames used by QGIS simple fills can be used as well:
Dynamic Labels (with PropertyName elements), Font and Halo are supported. No vendor-specific options are supported. LabelPlacement or PointPlacement are supported. Graphic elements to display behind the label text are not supported.
AnchorPointX
of 0.1 is snapped to 0, corresponding to left alignment in OpenLayers.[1]: according to the SLD-spec, label rotation takes place before displacement, but OpenLayers applies displacement before rotation. Beware when combining rotation and displacement inside a single text symbolizer.
According to the SLD spec, most values can be mixed type (a combination of plain text and Filter expressions). This means that most values can depend on feature properties.
SLDReader supports dynamic values in these cases:
stroke
stroke-opacity
stroke-width
fill
fill-opacity
font-family
font-style
font-weight
font-size
Note: dynamic parameter values currently have no effect on Marks used inside GraphicStroke or GraphicFill and will use SLD defaults instead.
Operators Add
, Sub
, Mul
, and Div
are implemented by converting them to function expressions.
Only pixels are supported as unit of measure.
The use of a Geometry element to point to a different geometry property on a feature to use for styling is not supported.
The SLDReader library supports the following operators inside Filter elements:
SLDReader can parse <Function>
elements, but the support for functions is vendor specific. Geoserver supports different functions than QGIS does. Since it's not feasible to support all possible vendor specific functions, SLDReader only supports a handful of them, listed below.
geometryType(geometry) -> string
dimension(geometry) -> integer
<Filter>
<PropertyIsEqualTo>
<Function name="dimension">
<PropertyName>geometry</PropertyName>
</Function>
<Literal>1</Literal>
</PropertyIsEqualTo>
</Filter>
substr(string, start, [length]) -> string
-N
means start N
characters from the end.length
characters from the end of the string.strSubstring(string, begin, end) -> string
strSubstringStart(string, begin) -> string
begin
index means: start at that many characters from the end of the string.in(test, ...candidates) -> boolean
true
if test
value is present in the list of candidates
arguments, using string-based, case sensitive, comparison.in('fox', 'the', 'quick', 'brown', 'fox') --> true
.in(2, '1', '2', '3') --> true
.in2..in10
in
function, coming from (older) GeoServer versions that required a different function for different parameter counts.It's possible to add support for a specific function yourself, using SLDReader.registerFunction(functionName, implementation)
.
Example:
SLDReader.registerFunction('strSubstringStart', (text, startIndex) =>
text.slice(startIndex)
);
After registering your function implementation, you can use it for example in a filter expression:
<Filter>
<PropertyIsEqualTo>
<Function name="strSubstringStart">
<PropertyName>title</PropertyName>
<Literal>2</Literal>
</Function>
<Literal>LLO WORLD</Literal>
</PropertyIsEqualTo>
</Filter>
The registered function will be called with the value of its child expressions as parameters.
Important notes:
<Literal>
expression parameters are always passed as string. If your function expects numeric parameters, convert accordingly.<PropertyName>
expressions depends on the feature. Typically, when serializing from GeoJSON, integer values are actual integers.'geometry'
for OpenLayers features by default.null
from a function implementation, the function fallback value will be used if one is specified in the SLD.
<Function name="someFunction" fallbackValue="42">
The SLDReader has a peer dependency on OpenLayers version 5.3.0. Because there are no backwards incompatible changes between v7+ and v5.3, it is possible to use this library in a project that uses a later (v8+) version of OpenLayers.
This may change in the future if the newest version of OpenLayers stops being backwards compatible with this library, or when a juicy new must-have feature is introduced. When that happens, SLDReader will be based on that OpenLayers version.
Some older browsers need polyfills to use this library. E.g. es6.array.find. When using the OpenLayers style converter, OpenLayers' own browser restrictions have to be taken into account as well.
Please include an example sld and if possible an example feature as GeoJSON.
Before starting on a pull request, please raise a Github issue first to prevent starting work on something we're already planning/working on.
When making a pull request, please:
To install dependencies, test, build and document
npm install
npm test
npm run build
npm run docs
docker-compose up (runs doc website on :4000)