OGC SLD/SE styling provides you with a number of possible ways to style a point on the map.
For simple graphics, like circles or squares, you can use the Mark
element.
For more complex graphics, you can use the ExternalGraphic
element.
For an ExternalGraphic
element, it’s possible to map any given string to icon images by specifying an
IconProvider
in the SEPainterCreateOptions
. To learn how to use the IconProvider
, see
Map ExternalGraphics to distinct icon images.
For a Mark
element, LuciadRIA allows you to use a function to define the WellKnownName
(WKN) of the mark. As a result, you can change the mark dynamically based on the feature properties.
Changing the Mark
element with the WKN extension
Using the WKN vendor-specific extension, you can map the element to the IconProvider
capability. This mapping allows you
to fully customize your point styling based on the feature properties. It combines:
-
Functions: use a custom function to choose the
WellKnownName
of theMark
element -
IconProvider: use the
IconProvider
to map theWellKnownName
to an icon image
You can create your own WellKnownName
in a custom function. If you want to use it to create a custom
icon, make sure that your WellKnownName
start with "LuciadIconProvider:\\"
. LuciadRIA forwards Mark
elements that have a name starting with "LuciadIconProvider:\\"
to the IconProvider
.
In your IconProvider
, you can parse the WellKnownName
string and return the correct icon image.
The
|
|
Example
This example shows you how to use the Mark
element with the WKN extension.
It renders the labels of some big cities in the USA as icons.

LuciadIconProvider:\\
mark rendering the labels as icons
First, you define a Function getIconProviderMark
that gets called to create the WellKnownName
of the mark.
In this case, the WellKnownName
is based on the NAME
property of the feature.
Expand for the code that creates the image:
<?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">
<Rule>
<PointSymbolizer>
<Graphic>
<Mark>
<WellKnownName>
<ogc:Function name="getIconProviderMark">
<ogc:PropertyName>NAME</ogc:PropertyName>
</ogc:Function>
</WellKnownName>
</Mark>
<Size>32</Size>
</Graphic>
</PointSymbolizer>
</Rule>
</FeatureTypeStyle>
Next, you provide the custom function getIconProviderMark
and the custom IconProvider
as an option to the SEPainterFactory
method.
createPainterFromString(seSource, {
functionEvaluators: {
"getIconProviderMark": (name: string): string => {
return `LuciadIconProvider://?name=${name}`;
}
},
iconProvider: {
getIcon(uri: string): HTMLImageElement | HTMLCanvasElement | string {
if (uri.indexOf("LuciadIconProvider://") > -1) {
/**
* In this case, the request for an icon comes from a Mark
* The uri is a stringified JSON object:
*
* const iconJson = {
* url: "LuciadIconProvider://${name}_#ff0000",
* iconOptions: IconOptions,
* }
* const uri = JSON.stringify(iconJson);
*/
try {
const iconJson = JSON.parse(uri);
const url = URL.parse(iconJson.url);
if (url !== null) {
const iconOptions: IconOptions = iconJson.iconOptions as IconOptions;
const nameString = url.searchParams.get("name") ?? "-";
const canvasNodeText: HTMLCanvasElement = document.createElement("canvas");
canvasNodeText.width = iconOptions.width ?? 256;
canvasNodeText.height = iconOptions.height ?? 256;
// draw large text, to have a sharp result!
const font = "bold 100px sans-serif";
const ctxText = canvasNodeText.getContext("2d")!;
// first fetch the size of the text
ctxText.font = font;
const textMetrics = ctxText.measureText(nameString);
// Create a new canvas with the size of the text
const canvasNode: HTMLCanvasElement = document.createElement("canvas");
const width = textMetrics.actualBoundingBoxRight + 20;
const height = textMetrics.hangingBaseline + 20;
canvasNode.width = width;
canvasNode.height = height;
const ctx = canvasNode.getContext("2d")!;
// create the background
ctx.fillStyle = "rgba(0,0,0,0)";//transparent
ctx.fillRect(0, 0, width, height);
// write the text
ctx.font = font;
ctx.fillStyle = "rgb(255,0,0)";
ctx.fillText(`${nameString}`, 10, height - 10);
// draw the border
ctx.strokeStyle = "rgb(0,0,255)";
ctx.lineWidth = 10;
ctx.strokeRect(0, 0, width, height);
return canvasNode;
}
} catch (e) {
}
}
return uri;
}
},
}).then(function(painter) {
map.layerTree.addChild(new FeatureLayer(model, {
painter: painter
}));
});
Although the |