forked from orfon/Leaflet.SLD
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathleaflet.sld.legend.js
155 lines (127 loc) · 7.16 KB
/
leaflet.sld.legend.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/**
* This class parses an SLD XML string and generates an SVG legend for each layer in the SLD.
* The legend is stored in the "legend" property of the class instance.
* The legend property is an object with a key for each layer in the SLD.
* Each layer key has an array of rules, where each rule is an object with the following properties:
* - name: the name of the rule
* - title: the title of the rule
* - svg: the SVG string for the rule
*
*/
export default class LeafletSldLegend {
constructor(sldStringOrXml) {
this.legend = {};
this.namespaceMapping = {
se: "http://www.opengis.net/se",
ogc: "http://www.opengis.net/ogc",
sld: "http://www.opengis.net/sld"
}
if (typeof sldStringOrXml === 'string') {
// Parse the SLD XML string into an XML document
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(sldStringOrXml, 'application/xml');
// Define the namespaces for "se" and "ogc"
// Iterate through the Layer styles in the SLD
const layerNodes = xmlDoc.querySelectorAll('NamedLayer');
for (const layerNode of layerNodes) {
const layerName = layerNode.getElementsByTagNameNS(this.namespaceMapping.se, 'Name')[0].textContent;
this.legend[layerName] = {
rules: []
};
// Iterate through the UserStyles in the NamedLayer
const userStyleNodes = layerNode.querySelectorAll('UserStyle');
for (const userStyleNode of userStyleNodes) {
let rules = userStyleNode.getElementsByTagNameNS(this.namespaceMapping.se, 'Rule');
for (const rule of rules) {
this.parseRule(rule, layerName);
}
}
}
} else {
throw new Error('Invalid input. Please provide an SLD XML string.');
}
}
parseRule(rule, layerName) {
// parses rules and creates an SVG with styles from the rule
const nameNode = rule.getElementsByTagNameNS(this.namespaceMapping.se, 'Name')[0];
const titleNode = rule.getElementsByTagNameNS(this.namespaceMapping.se, 'Title')[0];
if (!nameNode) {
return;
}
let ruleParsed = {
name: nameNode ? nameNode.textContent : 'No Name',
title: titleNode ? titleNode.textContent : 'No Title',
svg: this.generateSVGFromRule(rule, this.namespaceMapping)
};
this.legend[layerName].rules.push(ruleParsed);
}
generateSVGFromRule(ruleNode, namespaces) {
// Initialize an SVG string
let svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0,0,100,100">';
// Check if there's a PointSymbolizer in the rule
const pointSymbolizerNodes = ruleNode.getElementsByTagNameNS(namespaces.se, 'PointSymbolizer');
if (pointSymbolizerNodes.length > 0) {
const pointSymbolizerNode = pointSymbolizerNodes[0];
// Extract fill and stroke parameters from the PointSymbolizer
const fillNode = pointSymbolizerNode.querySelector('Fill');
const strokeNode = pointSymbolizerNode.querySelector('Stroke');
const wellKnownNameNode = pointSymbolizerNode.querySelector('WellKnownName');
const sizeNode = pointSymbolizerNode.querySelector('Size');
// Get fill color
let fillColorAttribute = "";
if (fillNode && fillNode.children.length) {
const fillColor = fillNode.querySelector('SvgParameter[name="fill"]').textContent;
fillColorAttribute = `fill="${fillColor}"`
}
// Get stroke color and width
let strokeAttributes = "";
if (strokeNode && strokeNode.children.length) {
const strokeColor = strokeNode ? strokeNode.querySelector('SvgParameter[name="stroke"]').textContent : 'none';
const strokeWidth = strokeNode ? strokeNode.querySelector('SvgParameter[name="stroke-width"]').textContent : '0';
strokeAttributes = `stroke="${strokeColor}" stroke-width="${strokeWidth}"`
}
// Get the well-known name for the shape
const wellKnownName = wellKnownNameNode ? wellKnownNameNode.textContent : '';
// Get the size of the shape
const size = sizeNode ? sizeNode.textContent : '0';
// Create an SVG representation of the shape (in this case, a circle)
svg += `<circle cx="50" cy="50" r="${size}" ${fillColorAttribute} ${strokeAttributes} />`;
} else {
// Check if there's a LineSymbolizer in the rule
const lineSymbolizerNodes = ruleNode.getElementsByTagNameNS(namespaces.se, 'LineSymbolizer');
if (lineSymbolizerNodes.length > 0) {
const lineSymbolizerNode = lineSymbolizerNodes[0];
// Extract stroke parameters from the LineSymbolizer
const strokeNode = lineSymbolizerNode.querySelector('Stroke');
const strokeWidthNode = strokeNode.querySelector('SvgParameter[name="stroke-width"]');
// Get stroke color and width
const strokeColor = strokeNode ? strokeNode.querySelector('SvgParameter[name="stroke"]').textContent : 'none';
const strokeWidth = strokeWidthNode ? strokeWidthNode.textContent : '0';
// Create an SVG representation of a line
svg += `<line x1="10" y1="50" x2="90" y2="50" stroke="${strokeColor}" stroke-width="${strokeWidth}" />`;
} else {
// Check if there's a PolygonSymbolizer in the rule
const polygonSymbolizerNodes = ruleNode.getElementsByTagNameNS(namespaces.se, 'PolygonSymbolizer');
if (polygonSymbolizerNodes.length > 0) {
const polygonSymbolizerNode = polygonSymbolizerNodes[0];
// Extract fill and stroke parameters from the PolygonSymbolizer
const fillNode = polygonSymbolizerNode.querySelector('Fill');
const strokeNode = polygonSymbolizerNode.querySelector('Stroke');
// Get fill color
const fillColor = fillNode ? fillNode.querySelector('SvgParameter[name="fill"]').textContent : 'none';
// Get stroke color and width
const strokeColor = strokeNode ? strokeNode.querySelector('SvgParameter[name="stroke"]').textContent : 'none';
const strokeWidth = strokeNode ? strokeNode.querySelector('SvgParameter[name="stroke-width"]').textContent : '0';
// Create an SVG representation of a rectangle
svg += `<rect x="10" y="10" width="80" height="80" fill="${fillColor}" stroke="${strokeColor}" stroke-width="${strokeWidth}" />`;
} else {
// Handle other symbolizers as needed
svg += '<text x="10" y="50" fill="red">Symbolizer not supported</text>';
}
}
}
// Close the SVG element
svg += '</svg>';
return svg;
}
}