Skip to content

Commit 021b4af

Browse files
authored
Merge pull request #481 from fschmenger/layer_legend_wms_styles_support
Layer legend wms styles support
2 parents cd08184 + add3faf commit 021b4af

3 files changed

Lines changed: 107 additions & 16 deletions

File tree

src/components/layerlist/LayerLegendImage.vue

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010
import LayerLegend from '@/util/LayerLegend';
1111
1212
/**
13-
* Module for one legend element.
13+
* Component rendering a legend image for a layer.
14+
* It reacts to:
15+
* - map view resolution changes
16+
* - layer source changes (e.g. WMS params updates)
1417
*/
1518
export default {
1619
name: 'wgu-layerlegendimage',
@@ -21,33 +24,77 @@ export default {
2124
data () {
2225
return {
2326
resolution: this.mapView.getResolution(),
24-
viewResolutionChanged: undefined
27+
viewResolutionChanged: undefined,
28+
sourceRevision: 0,
29+
sourceChanged: undefined
2530
}
2631
},
2732
/**
28-
* Register for an event to update the legend on resolution change.
33+
* Register event listeners.
2934
*/
3035
created () {
31-
const viewResolutionChanged = function (event) {
32-
this.resolution = event.target.getResolution();
33-
}.bind(this);
34-
35-
this.mapView.on('change:resolution', viewResolutionChanged);
36-
this.viewResolutionChanged = viewResolutionChanged;
36+
this.registerViewResolutionChanged(this.mapView);
37+
this.registerSourceChanged(this.layer?.getSource());
3738
},
3839
/**
39-
* Unregister the event fired on resolution change.
40+
* Unregister event listeners.
4041
*/
4142
unmounted () {
42-
if (this.viewResolutionChanged) {
43-
this.mapView.un('change:resolution', this.viewResolutionChanged);
43+
this.unregisterViewResolutionChanged(this.mapView);
44+
this.unregisterSourceChanged(this.layer?.getSource());
45+
},
46+
methods: {
47+
/**
48+
* Registers a listener for map view resolution changes.
49+
*/
50+
registerViewResolutionChanged (view) {
51+
if (!view) return;
52+
53+
this.viewResolutionChanged = (event) => {
54+
this.resolution = event.target.getResolution();
55+
};
56+
57+
view.on('change:resolution', this.viewResolutionChanged);
58+
},
59+
/**
60+
* Unregisters the resolution change listener.
61+
*/
62+
unregisterViewResolutionChanged (view) {
63+
if (view && this.viewResolutionChanged) {
64+
view.un('change:resolution', this.viewResolutionChanged);
65+
}
66+
},
67+
/**
68+
* Registers a listener for source changes.
69+
*/
70+
registerSourceChanged (source) {
71+
if (!source) return;
72+
73+
this.sourceChanged = () => {
74+
this.sourceRevision++;
75+
};
76+
77+
source.on('change', this.sourceChanged)
78+
},
79+
/**
80+
* Unregisters the source change listener.
81+
*/
82+
unregisterSourceChanged (source) {
83+
if (source && this.sourceChanged) {
84+
source.un('change', this.sourceChanged);
85+
}
4486
}
4587
},
4688
computed: {
4789
/**
4890
* Returns a URL to the layers legend image.
4991
*/
5092
legendURL () {
93+
// Remarks: No-op to force dependency tracking on the sourceRevision
94+
// counter to recompute the legendURL whenever the source changes.
95+
const trackRevision = () => { return this.sourceRevision };
96+
trackRevision();
97+
5198
const legendUtil = new LayerLegend(this.$appConfig?.legend);
5299
const options = {
53100
language: this.$i18n.locale,
@@ -56,6 +103,22 @@ export default {
56103
return legendUtil.getUrl(
57104
this.layer, this.resolution, options, this.layer.get('legendUrl'));
58105
}
106+
},
107+
watch: {
108+
/**
109+
* Reacts to layer replacement and rebinds source listeners.
110+
*/
111+
layer: {
112+
handler (newLayer, oldLayer) {
113+
const newSource = newLayer?.getSource?.();
114+
const oldSource = oldLayer?.getSource?.();
115+
116+
if (newSource !== oldSource) {
117+
this.unregisterSourceChanged(oldSource);
118+
this.registerSourceChanged(newSource);
119+
}
120+
}
121+
}
59122
}
60123
};
61124
</script>

src/util/LayerLegend.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,23 @@ const WMSSourceLegend = {
103103
* @returns {String} The legend URL.
104104
*/
105105
getUrl (source, resolution, options) {
106+
const legendOptions = { ...options };
107+
106108
const wmsParams = source.getParams();
107109
const wmsVersion = ObjectUtil.getValueIgnoreCase(wmsParams, 'VERSION') || '1.3.0';
108-
// apply mandatory SLD_VERSION param for WMS 1.3.0 GetLegendGraphic request
109-
if (wmsVersion === '1.3.0' && !ObjectUtil.getValueIgnoreCase(options, 'SLD_VERSION')) {
110-
options.SLD_VERSION = '1.1.0';
110+
111+
// Apply mandatory SLD_VERSION param for WMS 1.3.0 GetLegendGraphic request.
112+
if (wmsVersion === '1.3.0' && !ObjectUtil.getValueIgnoreCase(legendOptions, 'SLD_VERSION')) {
113+
legendOptions.SLD_VERSION = '1.1.0';
114+
}
115+
116+
// Forward STYLES param, which may affect the legends appearance.
117+
const wmsStyle = ObjectUtil.getValueIgnoreCase(wmsParams, 'STYLES');
118+
if (wmsStyle && !ObjectUtil.getValueIgnoreCase(legendOptions, 'STYLE')) {
119+
legendOptions.STYLE = wmsStyle;
111120
}
112121

113-
return source.getLegendUrl(resolution, options);
122+
return source.getLegendUrl(resolution, legendOptions);
114123
}
115124
}
116125

tests/unit/specs/components/layerlist/LayerLegendImage.spec.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,25 @@ describe('layerlist/LayerLegendImage.vue', () => {
170170
'SCALE=3571428.571428572&language=de&SLD_VERSION=1.1.0');
171171
});
172172

173+
it('legendURL supports WMS style parameter', async () => {
174+
await comp.setProps({ layer: wmsLayer });
175+
176+
expect(vm.legendURL).to.equal('https://ahocevar.com/geoserver/wms?' +
177+
'SERVICE=WMS&VERSION=1.3.0&REQUEST=GetLegendGraphic&FORMAT=image%2Fpng&LAYER=topp%3Astates&' +
178+
'SCALE=3571428.571428572&language=en&SLD_VERSION=1.1.0');
179+
180+
const source = wmsLayer.getSource();
181+
const params = source.getParams();
182+
source.updateParams({
183+
...params,
184+
STYLES: 'foo'
185+
});
186+
187+
expect(vm.legendURL).to.equal('https://ahocevar.com/geoserver/wms?' +
188+
'SERVICE=WMS&VERSION=1.3.0&REQUEST=GetLegendGraphic&FORMAT=image%2Fpng&LAYER=topp%3Astates&' +
189+
'SCALE=3571428.571428572&language=en&SLD_VERSION=1.1.0&STYLE=foo');
190+
})
191+
173192
afterEach(() => {
174193
vm.$i18n.locale = 'en';
175194
comp.unmount();

0 commit comments

Comments
 (0)