Skip to content

Commit 1d14fdb

Browse files
committed
New script - Show a global legend image for all visible layers
1 parent b190174 commit 1d14fdb

4 files changed

Lines changed: 123 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ the script was written.
8585
* [Export attribute table to CSV](./library/ui/export-attributetable-csv)
8686
* [Add button to toggle dock full width](./library/ui/add_dock_resize_button)
8787
* [Add a hard-coded legend at the bottom of the map](./library/ui/add_hard_coded_legend_at_map_bottom)
88+
* [Show a global legend image for all visible layers](./library/ui/show_global_legend_image)
8889
* [Add placeholder to input/textarea elements](./library/ui/add_placeholder_on_text_controls)
8990
* [Permalink copy to clipboard instead of link](./library/ui/copy-permalink)
9091
* [Move Layers button after Information](./library/ui/move-button)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Show a global legend image for all visible layers
2+
3+
This scripts adds a new menu item called `Legend` which let the user open a small panel on the top-right corner of the map showing the image legend of the currently active layers.
4+
5+
The legend image is refreshed automatically when the user:
6+
7+
* Toggles the visibility of the map layers in the `Layers` panel
8+
* zooms or pans the map:
9+
* the legend classes will be visible if the corresponding objects are visible in the map
10+
* the legend will change accordingly to the map scale
11+
* and only if the legend panel is visible.
12+
13+
You can edit the JavaScript file to change the label of the tool: replace `Legend` by any other term for the constant `MY_LEGEND_TITLE`.
14+
15+
![show_global_legend_image.gif](./show_global_legend_image.gif)
3.6 MB
Loading
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
const MY_LEGEND_TITLE = 'Legend';
2+
3+
/**
4+
* Refresh the content of the given target container
5+
* with the image corresponding to all active & visible layers
6+
* @param {HTMLElement} targetElement Target element where to display the legend image
7+
*/
8+
function refreshGlobalLegendImage(targetElement) {
9+
// Do not refresh legend if mini-dock is not visible
10+
const isVisible = document.getElementById('global_legend').checkVisibility();
11+
if (!isVisible) {
12+
return;
13+
}
14+
15+
// console.log('Refresh global legend');
16+
17+
// Get Lizmap active layers
18+
let params = lizMap.mainLizmap.wms._defaultGetLegendGraphicParameters;
19+
const activeLayers = lizMap.mainLizmap.state.layersAndGroupsCollection.layers.filter(l => (l.checked && l.visibility));
20+
wmsNames = activeLayers.map(layer => layer.wmsName);
21+
if (wmsNames.length == 0) return;
22+
23+
wmsStyles = activeLayers.map(layer => layer.wmsSelectedStyleName);
24+
params['LAYERS'] = wmsNames.join();
25+
params['STYLE'] = wmsStyles.join();
26+
params['FORMAT'] = 'image/png';
27+
params['BBOX'] = lizMap.mainLizmap.state.map.extent.join();
28+
params['CRS'] = lizMap.mainLizmap.state.map.projection;
29+
params['SRCWIDTH'] = lizMap.mainLizmap.state.map.size[0];
30+
params['SRCHEIGHT'] = lizMap.mainLizmap.state.map.size[1];
31+
32+
// Set GetLegendGraphics WMS request
33+
lizMap.mainLizmap.utils.fetch(globalThis['lizUrls'].wms, {
34+
method: "POST",
35+
body: new URLSearchParams(params)
36+
}).then((response) => {
37+
if (response.status === 200) {
38+
return response.blob();
39+
}
40+
else {
41+
console.error("HTTP-Error: " + response.status)
42+
}
43+
}).then((blob) => {
44+
const imageUrl = URL.createObjectURL(blob);
45+
const imageElement = document.createElement('img');
46+
imageElement.src = imageUrl;
47+
targetElement.innerHTML = '';
48+
targetElement.appendChild(imageElement);
49+
}).catch(console.error);
50+
}
51+
52+
lizMap.events.on({
53+
'uicreated': function(event) {
54+
55+
// Legend HTML
56+
const legend_html = `
57+
<div class="my-legend-container">
58+
<div id="my-legend-items-container">
59+
</div>
60+
</div>
61+
`;
62+
63+
// Create mini-dock
64+
lizMap.addDock(
65+
'global_legend',
66+
MY_LEGEND_TITLE,
67+
'minidock',
68+
legend_html,
69+
'icon-tasks'
70+
);
71+
72+
const targetContainer = document.getElementById('my-legend-items-container');
73+
74+
// Insert image on first load
75+
refreshGlobalLegendImage(targetContainer);
76+
77+
// Refresh image on layers/group change
78+
lizMap.mainLizmap.state.rootMapGroup.addListener(
79+
() => refreshGlobalLegendImage(targetContainer),
80+
['layer.visibility.changed', 'group.visibility.changed', 'layer.style.changed', 'group.style.changed']
81+
);
82+
83+
// Refresh image on zoom change
84+
// We might trigger this on extent change,
85+
// but it will increase the number of requests
86+
// Useful only if bbox parameter is passed
87+
// and if QGIS Server returns only visible symbology classes
88+
lizMap.mainLizmap.state.map.addListener(
89+
evt => {
90+
if (evt.hasOwnProperty('zoom')) {
91+
refreshGlobalLegendImage(targetContainer);
92+
}
93+
},
94+
['map.state.changed']
95+
);
96+
},
97+
98+
'minidockopened': function(event) {
99+
if (event.id == 'global_legend') {
100+
const targetContainer = document.getElementById('my-legend-items-container');
101+
if (targetContainer) {
102+
refreshGlobalLegendImage(targetContainer);
103+
}
104+
}
105+
}
106+
107+
});

0 commit comments

Comments
 (0)