diff options
author | Guilhem Moulin <guilhem@fripost.org> | 2025-06-07 23:41:44 +0200 |
---|---|---|
committer | Guilhem Moulin <guilhem@fripost.org> | 2025-06-08 15:14:57 +0200 |
commit | ce8488b488ac218cb5b9fcf72873dc7b3d836531 (patch) | |
tree | 3682e53867dc8c4c9de9437b730440a9950ae6f0 | |
parent | 1fcf00277a18c5231a2c3475071ba644373f1f76 (diff) |
Add a dynamic legend.
(Long overdue…)
-rw-r--r-- | main.js | 244 | ||||
-rw-r--r-- | style.css | 51 |
2 files changed, 274 insertions, 21 deletions
@@ -39,6 +39,11 @@ import { createXYZ } from 'ol/tilegrid.js'; import VectorLayer from 'ol/layer/Vector.js'; import VectorSource from 'ol/source/Vector.js'; +import { toContext } from 'ol/render.js'; +import Polygon from 'ol/geom/Polygon.js'; +import LineString from 'ol/geom/LineString.js'; +import Point from 'ol/geom/Point.js'; + import CircleStyle from 'ol/style/Circle.js'; import Fill from 'ol/style/Fill.js'; import Icon from 'ol/style/Icon.js'; @@ -733,6 +738,7 @@ const layers = { //['Kommun', 'Municipality'], //['Län', 'County'], ], + legend: { zoomLevel: 4 }, style: [0, .1, .5, .5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 22, @@ -758,6 +764,7 @@ const layers = { //['Kommun', 'Municipality'], //['Län', 'County'], ], + legend: { zoomLevel: 4 }, style: [0, .1, .5, .5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 25, @@ -788,6 +795,7 @@ const layers = { //['Kommun', 'Municipality'], //['Län', 'County'], ], + legend: { zoomLevel: 4 }, style: [0, .1, .5, .5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 24, @@ -813,6 +821,7 @@ const layers = { //['Kommun', 'Municipality'], //['Län', 'County'], ], + legend: { zoomLevel: 4 }, style: [0, .1, .5, .5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 26, @@ -843,6 +852,7 @@ const layers = { //['Kommun', 'Municipality'], //['Län', 'County'], ], + legend: { zoomLevel: 4 }, style: [0, .1, .5, .5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 24, @@ -868,6 +878,7 @@ const layers = { //['Kommun', 'Municipality'], //['Län', 'County'], ], + legend: { zoomLevel: 4 }, style: [0, .1, .5, .5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 26, @@ -895,6 +906,7 @@ const layers = { //['Kommun', 'Municipality'], //['Län', 'County'], ], + legend: { zoomLevel: 4 }, style: [0, .1, .5, .5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 20, @@ -916,6 +928,7 @@ const layers = { ['Spänning', 'Voltage', { unit: 'kV' }], ['Ledlängd', 'geom_length', { fn: 'length' }], ], + legend: { zoomLevel: 5, type: 'linestring', reuse_canvas: true }, style: [1, 1.5, 2, 2, 2, 2, 3, 4, 5, 6, 8, 10].map(function(width) { return new Style({ zIndex: 52, @@ -927,6 +940,7 @@ const layers = { }), }, 'svk.stolpar': { + legend: { zoomLevel: 5, type: 'point' }, style: [undefined, undefined, undefined, undefined, undefined] .concat([3, 4, 5, 6, 8, 10, 15].map(function(radius) { return new Style({ @@ -955,6 +969,7 @@ const layers = { return a; }}], ], + legend: { zoomLevel: 5, type: 'linestring' }, style: [1, 1.5, 2, 2, 2, 2, 3, 4, 5, 6, 8, 10].map(function(width) { return new Style({ zIndex: 53, @@ -967,6 +982,7 @@ const layers = { }), }, 'svk.stationer': { + legend: { zoomLevel: 3, type: 'point' }, style: [3, 4, 5, 6, 7, 8.5, 10].map(function(radius) { return new Style({ zIndex: 50, @@ -1014,6 +1030,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Senast uppdaterat', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 1 }, style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 10, @@ -1046,6 +1063,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Senast uppdaterat', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 1 }, style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 10, @@ -1085,6 +1103,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Senast uppdaterat', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 1 }, style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 17, @@ -1129,6 +1148,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Senast uppdaterat', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 1 }, style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 16, @@ -1168,6 +1188,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Senast uppdaterat', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 2 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -1220,6 +1241,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Senast uppdaterat', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 1 }, style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 11, @@ -1262,6 +1284,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Senast uppdaterat', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 1 }, style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 15, @@ -1300,6 +1323,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Senast uppdaterat', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 1 }, style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 14, @@ -1337,6 +1361,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Senast uppdaterat', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 1 }, style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 13, @@ -1373,6 +1398,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Senast uppdaterat', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 1 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -1438,6 +1464,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Senast uppdaterat', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 1 }, style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 10, @@ -1476,6 +1503,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Datum för senaste uppdatering av verk', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 7, type: 'point' }, style: [undefined, undefined, undefined, undefined, .125, .125, .25, .5, 1, 2, 4, 8].map(function(scale) { return scale === undefined ? undefined : new Style({ zIndex: 99, @@ -1510,6 +1538,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Datum för senaste uppdatering av verk', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 7, type: 'point' }, style: [undefined, undefined, undefined, undefined, .125, .125, .25, .5, 1, 2, 4, 8].map(function(scale) { return scale === undefined ? undefined : new Style({ zIndex: 99, @@ -1545,6 +1574,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Datum för senaste uppdatering av verk', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 7, type: 'point' }, style: [undefined, undefined, undefined, undefined, .125, .125, .25, .5, 1, 2, 4, 8].map(function(scale) { return scale === undefined ? undefined : new Style({ zIndex: 99, @@ -1580,6 +1610,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Datum för senaste uppdatering av verk', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 7, type: 'point' }, style: [undefined, undefined, undefined, undefined, .125, .125, .25, .5, 1, 2, 4, 8].map(function(scale) { return scale === undefined ? undefined : new Style({ zIndex: 99, @@ -1615,6 +1646,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Datum för senaste uppdatering av verk', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 7, type: 'point' }, style: [undefined, undefined, undefined, undefined, .125, .125, .25, .5, 1, 2, 4, 8].map(function(scale) { return scale === undefined ? undefined : new Style({ zIndex: 99, @@ -1650,6 +1682,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Datum för senaste uppdatering av verk', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 7, type: 'point' }, style: [undefined, undefined, undefined, undefined, .125, .125, .25, .5, 1, 2, 4, 8].map(function(scale) { return scale === undefined ? undefined : new Style({ zIndex: 99, @@ -1684,6 +1717,7 @@ const layers = { ['Elområde', 'ElNamn'], ['Datum för senaste uppdatering av verk', 'SenasteUppdaterat'], ], + legend: { zoomLevel: 7, type: 'point' }, style: [undefined, undefined, undefined, undefined, .125, .125, .25, .5, 1, 2, 4, 8].map(function(scale) { return scale === undefined ? undefined : new Style({ zIndex: 99, @@ -1716,6 +1750,7 @@ const layers = { //['Län', 'Lan'], ['Areal för ytan', 'geom_area', { fn: 'area' }], ], + legend: { zoomLevel: 7 }, style: [0, 0, 0, 0, 0, .5, .75, 1, 1, 1, 1, 1].map(function(width, z) { return new Style({ zIndex: 10, @@ -1750,6 +1785,7 @@ const layers = { ['Ärendestatus', 'ArendeStatus'], ['Avverkad areal', 'AvvHa', { unit: 'ha' }], ], + legend: { zoomLevel: 7 }, style: [0, 0, 0, 0, 0, .5, .75, 1, 1, 1, 1, 1].map(function(width, z) { return new Style({ zIndex: 10, @@ -1804,6 +1840,7 @@ const layers = { ['Beskrivning', 'BESKRIVN'], ['Areal', 'geom_area', { fn: 'area' }], ], + legend: { zoomLevel: 2 }, style: [1, 1.5, 2, 3, 3.5, 4, 5, 5, 6, 7, 8, 10].map(function(width, z) { return new Style({ zIndex: 23, @@ -1839,6 +1876,7 @@ const layers = { ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], ], + legend: { zoomLevel: 1 }, style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -1892,6 +1930,7 @@ const layers = { ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], ], + legend: { zoomLevel: 1 }, style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -1945,6 +1984,7 @@ const layers = { ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], ], + legend: { zoomLevel: 2 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -1998,6 +2038,7 @@ const layers = { ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], ], + legend: { zoomLevel: 2 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2051,6 +2092,7 @@ const layers = { ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], ], + legend: { zoomLevel: 2 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2104,6 +2146,7 @@ const layers = { ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], ], + legend: { zoomLevel: 2 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2157,6 +2200,7 @@ const layers = { ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], ], + legend: { zoomLevel: 2 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2210,6 +2254,7 @@ const layers = { ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], ], + legend: { zoomLevel: 2 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2263,6 +2308,7 @@ const layers = { return a; }}], ], + legend: { zoomLevel: 2 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2316,6 +2362,7 @@ const layers = { ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], ], + legend: { zoomLevel: 2 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2369,6 +2416,7 @@ const layers = { ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], ], + legend: { zoomLevel: 2 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2419,6 +2467,7 @@ const layers = { ['Beslutsmyndighet', 'BESLMYND'], ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], ], + legend: { zoomLevel: 6, type: 'point' }, style: [undefined, undefined, undefined, undefined].concat([3, 4, 6, 8, 12, 16, 20, 24].map(function(width, z) { return new Style({ zIndex: 12, @@ -2455,6 +2504,7 @@ const layers = { ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], ], + legend: { zoomLevel: 2 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2514,6 +2564,7 @@ const layers = { return a; }}], ], + legend: { zoomLevel: 1 }, style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2581,6 +2632,7 @@ const layers = { return a; }}], ], + legend: { zoomLevel: 1 }, style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2628,6 +2680,7 @@ const layers = { ['Namn', 'NAME'], ['Areal', 'geom_area', { fn: 'area' }], ], + legend: { zoomLevel: 1 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2679,6 +2732,7 @@ const layers = { return a; }}], ], + legend: { zoomLevel: 1 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2714,6 +2768,7 @@ const layers = { ['N2000-ID', 'N2000_SITE', { classes: ['feature-objid'] }], ['Areal', 'geom_area', { fn: 'area' }], ], + legend: { zoomLevel: 1 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2745,6 +2800,7 @@ const layers = { ['Namn', 'NAMN'], ['Areal', 'geom_area', { fn: 'area' }], ], + legend: { zoomLevel: 1 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2789,6 +2845,7 @@ const layers = { }}], ['Areal', 'geom_area', { fn: 'area' }], ], + legend: { zoomLevel: 1 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2826,6 +2883,7 @@ const layers = { ['Satus', 'STATUS'], ['Areal', 'geom_area', { fn: 'area' }], ], + legend: { zoomLevel: 1 }, style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2880,6 +2938,7 @@ const layers = { }}], ['Undertyp', 'Undertyp'], ], + legend: { zoomLevel: 2 }, style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -2933,6 +2992,7 @@ const layers = { return a; }}], ], + legend: { zoomLevel: 0 }, style: [0, 1, 2, 3, 4, 5, 6].map(function(width) { return new Style({ zIndex: 5, @@ -3004,6 +3064,7 @@ const layers = { return a; }}], ], + legend: { zoomLevel: 0 }, style: [0, 1, 2, 3, 4, 5].map(function(width) { return new Style({ zIndex: 6, @@ -3080,6 +3141,7 @@ const layers = { return a; }}], ], + legend: { zoomLevel: 0 }, style: [0, 1, 2, 3, 4, 5].map(function(width) { return new Style({ zIndex: 6, @@ -3144,6 +3206,7 @@ const layers = { return a; }}], ], + legend: { zoomLevel: 0 }, style: [0, 1, 2, 3, 4, 5].map(function(width) { return new Style({ zIndex: 6, @@ -3224,11 +3287,12 @@ const layers = { return a; }}], ], + legend: { zoomLevel: 5 }, style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); const w = Math.max(1, width); - patternCanvas.width = 8; + patternCanvas.width = z < 2 ? 2 : z < 4 ? 4 : z <= 5 ? 6 : 8; patternCanvas.height = patternCanvas.width; patternContext.fillStyle = 'transparent'; patternContext.strokeStyle = 'rgba(158, 200, 215, 1)'; @@ -3259,6 +3323,7 @@ const layers = { ['Senast justerat', 'GRANSJUST'], /* XXX unclear what "GRANSJUST" means, just a guess */ ['Areal', 'geom_area', { fn: 'area' }], ], + legend: { zoomLevel: 1 }, style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -3316,6 +3381,7 @@ const layers = { ['Länsstyrelsens bedömning', 'LST_BEDOMN'], ['Källor', 'KALLOR'], ], + legend: { zoomLevel: 1 }, style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { return new Style({ zIndex: 4, @@ -3354,6 +3420,7 @@ const layers = { ['Riks-ID', 'RIKSID', { classes: ['feature-objid'] }], ['Areal', 'geom_area', { fn: 'area' }], ], + legend: { zoomLevel: 0 }, style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -3421,6 +3488,7 @@ const layers = { ['Areal land', 'AREA_LAND_', { unit: 'ha' }], ['Areal vatten', 'AREA_VATTE', { unit: 'ha' }], ], + legend: { zoomLevel: 0 }, style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -3479,6 +3547,7 @@ const layers = { ['Areal', 'geom_area', { fn: 'area' }], ['Referens', 'REFERENS'], ], + legend: { zoomLevel: 0 }, style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -3540,6 +3609,7 @@ const layers = { ['Areal', 'geom_area', { fn: 'area' }], ['Referens', 'REFERENS'], ], + legend: { zoomLevel: 0 }, style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -3599,6 +3669,7 @@ const layers = { ['Areal', 'geom_area', { fn: 'area' }], ['Referens', 'REFERENS'], ], + legend: { zoomLevel: 0 }, style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -3660,6 +3731,7 @@ const layers = { ['Areal', 'geom_area', { fn: 'area' }], ['Referens', 'REFERENS'], ], + legend: { zoomLevel: 0 }, style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { return new Style({ zIndex: 8, @@ -3683,6 +3755,7 @@ const layers = { ['Signatur', 'SIGNATUR'], ['Aktualitet', 'AKTUALITET'], ], + legend: { zoomLevel: 0 }, style: [1, 1.5, 2, 3, 3.5, 4, 5, 5, 6, 7, 8, 10].map(function(width, z) { return new Style({ zIndex: 4, @@ -3713,6 +3786,7 @@ const layers = { ['Signatur', 'SIGNATUR'], ['Ledlängd', 'geom_length', { fn: 'length' }], ], + legend: { zoomLevel: 2, type: 'linestring' }, style: [.75, 1, 1.5, 2, 3, 4, 5, 5, 6, 7, 8, 10].map(function(width, z) { return new Style({ zIndex: 7, @@ -3732,6 +3806,7 @@ const layers = { ['Signatur', 'SIGNATUR'], ['Areal', 'geom_area', { fn: 'area' }], ], + legend: { zoomLevel: 1 }, style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { const patternCanvas = document.createElement('canvas'); const patternContext = patternCanvas.getContext('2d'); @@ -3771,6 +3846,7 @@ const layers = { ['Signatur', 'SIGNATUR'], ['Areal', 'geom_area', { fn: 'area' }], ], + legend: { zoomLevel: 2 }, style: [.5, .5, 1, 1, 1, 1.5, 1.5, 1.5, 2, 2, 2, 2].map(function(width, z) { return new Style({ zIndex: 5, @@ -3829,6 +3905,7 @@ const layers = { ['Reglerbar volym', 'RV', { unit: 'Mm³' }], ['Kommentar', 'Kommentar'], ], + legend: { zoomLevel: 5, type: 'point' }, style: [2, 3, 4, 4, 4, 6, 8, 8, 8, 10, 16, 32].map(function(width) { return new Style({ zIndex: 59, @@ -3860,6 +3937,7 @@ const layers = { return a; }}], ], + legend: { zoomLevel: 1, type: 'point' }, style: [4, 6, 7, 8, 10, 12].map(function(width) { return new Style({ zIndex: 60, @@ -3901,7 +3979,7 @@ const layerHierarchy = [ children: [ { text: 'Kraftledningar (befintliga)', - layer: ['svk.ledningar', 'svk.stolpar'], + layer: ['svk.stolpar', 'svk.ledningar'], }, { text: 'Stationer', @@ -4411,6 +4489,133 @@ const [mapLayers, featureOverlayLayer] = (function() { })(); +/* legend panel */ +(function() { + const modal = document.getElementById('map-legend-panel'); + modal.classList.add('modal'); + modal.setAttribute('role', 'dialog'); + modal.setAttribute('aria-hidden', 'true'); + + const content = document.createElement('div'); + modal.appendChild(content); + content.classList.add('modal-content'); + + const body = document.createElement('div'); + content.appendChild(body); + body.classList.add('modal-body'); + + const createLegend = function(ul, elem, classes) { + const li = document.createElement('li'); + li.classList.add('list-group-item'); + ul.append(li); + + const t = document.createTextNode(elem.text); + if (elem.layer === undefined) { + li.appendChild(t); + li.classList.add('map-legend-header'); + } else { + li.classList.add('d-flex', 'flex-row'); + const div = document.createElement('div'); + div.classList.add('map-legend-symbol'); + li.appendChild(div); + const parent_height = 24; /* see CSS */ + const [width, height] = [32, 20]; + const symbols = { + polygon: new Polygon([[ + [0, (parent_height-height)/2], + [width, (parent_height-height)/2], + [width, (parent_height+height)/2], + [0, (parent_height+height)/2], + [0, (parent_height-height)/2], + ]]), + linestring: new LineString([ + [0, parent_height/2], + [width, parent_height/2] + ]), + point: new Point( + [width/2, parent_height/2] + ), + }; + let canvas = null, render = null; + (Array.isArray(elem.layer) ? elem.layer : [elem.layer]) + .forEach(function(layer) { + /* add symbols for each layer */ + const layerGroup = layer.split('.', 1)[0]; + if (!layerGroup || !mapLayers[layerGroup] || !layers[layer] || !layers[layer].style) { + console.log(`Could not find symbol for layer ${layer}, skipping`); + return; + } + const legend = layers[layer].legend || {}; + if (canvas === null || !legend.reuse_canvas) { + canvas = document.createElement('canvas'); + div.appendChild(canvas); + render = toContext(canvas.getContext('2d'), + { size:[width, parent_height] } + ); + } + + if (mapLayers[layerGroup].getSource() instanceof GeoTIFF) { + /* raster source */ + render.setFillStrokeStyle(new Fill({ + color: layers[layer].style, + })); + return render.drawGeometry(symbols.polygon); + } + else if (mapLayers[layerGroup].getSource() instanceof VectorTile) { + /* vector source */ + const style = Array.isArray(layers[layer].style) ? + layers[layer].style[legend.zoomLevel ?? 5] : + layers[layer].style; + const legend_type = legend.type ?? 'polygon'; + if (legend_type === 'point' && style.getImage(1) instanceof Icon && style.getImage(1).getSrc()) { + /* use a new <img> element since .setStyle() returns the same one and doesn't work in that case */ + const div2 = document.createElement('div'); + const img = document.createElement('img'); + div2.appendChild(img); + img.src = style.getImage(1).getSrc(); + img.height = height; + div.replaceChild(div2, canvas); + } else { + const style2 = style.clone(); + const stroke = style2.getStroke(); + if (legend_type === 'polygon' && stroke && stroke.getWidth() > 1) { + /* don't stroke too wide to avoid spilling over boxes above/below */ + stroke.setWidth(1); + } + render.setStyle(style2); + return render.drawGeometry(symbols[legend_type]); + } + } + else { + throw new Error(`Cannot show legend for ${layer}`); + } + }); + const span = document.createElement('div'); + span.appendChild(t); + li.appendChild(span); + } + + elem._legend = li; + if (elem.children !== undefined && elem.children.length > 0) { + if (classes.length > 0) { + li.classList.add(classes[0]); + classes = classes.slice(1); + } + const ul2 = document.createElement('ul'); + ul2.classList.add('list-group', 'list-group-flush'); + ul.appendChild(ul2); + elem.children.forEach((elem2) => createLegend(ul2, elem2, classes)); + } + }; + + const ul = document.createElement('ul'); + ul.classList.add('list-group', 'list-group-flush'); + body.appendChild(ul); + layerHierarchy.forEach(function(x) { + createLegend(ul, x, ['h4', 'h5', 'h6']); + }); +})(); + /* layer selection panel */ const infoMetadataAccordions = []; (function() { @@ -4451,9 +4656,17 @@ const infoMetadataAccordions = []; const layerStyles = elem._layers.map((lyr) => styles[lyr] !== undefined); elem._input.indeterminate = elem._layers.length <= 1 ? false : layerStyles.slice(1).some((v) => v !== layerStyles[0]); - if (!elem._input.indeterminate) { + if (elem._input.indeterminate) { + elem._legend.classList.remove('d-none'); + } else { /* keep checked value if indeterminate */ - elem._input.checked = layerStyles.every((v) => v); + const checked = layerStyles.every((v) => v); + elem._input.checked = checked; + if (checked) { + elem._legend.classList.remove('d-none'); + } else { + elem._legend.classList.add('d-none'); + } } if (elem.children !== undefined && elem.children.length > 0) { setIndeterminateAndChecked(elem.children); @@ -4488,6 +4701,12 @@ const infoMetadataAccordions = []; v.setVisible(visible); } }); + const btn = document.getElementById('map-legend-button'); + if (Object.values(styles).some((v) => v !== null)) { + btn.classList.remove('disabled'); + } else { + btn.classList.add('disabled'); + } }; const onClickFunction = function(layerList, event) { featureOverlayLayer.setVisible(false); @@ -4710,23 +4929,6 @@ const infoMetadataAccordions = []; })(); })(); -/* legend panel */ -(function() { - const modal = document.getElementById('map-legend-panel'); - modal.classList.add('modal'); - modal.setAttribute('role', 'dialog'); - modal.setAttribute('aria-hidden', 'true'); - - const content = document.createElement('div'); - modal.appendChild(content); - content.classList.add('modal-content'); - - const body = document.createElement('div'); - content.appendChild(body); - body.classList.add('modal-body'); - body.innerHTML = 'legend TODO'; -})(); - /* popup and feature overlays */ (function() { const popupOverlay = new Overlay({ @@ -222,6 +222,11 @@ body.inprogress { opacity: 1; } } +#map-legend-panel .modal-body { + -webkit-user-select: text; + -moz-user-select: text; + user-select: text; +} #layer-selection-panel[aria-hidden="false"], #map-legend-panel[aria-hidden="false"] { animation: fade-in .25s ease-in-out both; @@ -250,6 +255,10 @@ body.inprogress { } } +#map-legend-button.disabled button { + color: rgb(from var(--bs-btn-color) r g b / calc(alpha*.25)); + pointer-events: none; +} @media screen and (max-width: 200px) { #layer-selection-button, #map-legend-button, @@ -397,6 +406,48 @@ body.inprogress { #layer-selection-panel .accordion-item .form-check > .form-check-label { display: inline; } +#map-legend-panel .list-group-flush > .list-group-item { + border: none; + padding: 0; +} +#map-legend-panel .modal-body > ul.list-group > li.list-group-item:not(.d-none) ~ li.list-group-item:not(.d-none) { + border-top: var(--bs-list-group-border-width) solid var(--bs-list-group-border-color); + margin-top: .5rem; + padding-top: .5rem; +} +#map-legend-panel .list-group .list-group-item.h4, +#map-legend-panel .list-group .list-group-item.h5, +#map-legend-panel .list-group .list-group-item.h6 { + margin: 0 0 .25rem 0; +} +#map-legend-panel .list-group .list-group-item:not(.d-none) ~ .list-group-item.h5:not(.d-none) { + margin-top: .125rem; +} +#map-legend-panel .list-group .list-group-item.h4 { + font-size: 1.3rem; +} +#map-legend-panel .list-group .list-group-item.h5 { + font-size: 1.05rem; +} +#map-legend-panel .list-group .list-group-item.h6 { + font-size: 1rem; +} +#map-legend-panel .list-group .list-group-item .map-legend-symbol { + /* 24px */ + height: calc(var(--bs-body-line-height) * var(--bs-body-font-size)) !important; +} +#map-legend-panel .list-group .list-group-item .map-legend-symbol > * { + width: 32px; + margin-right: .5rem; +} +#map-legend-panel .list-group .list-group-item .map-legend-symbol img { + margin-left: auto; + margin-right: auto; + display: block; +} +#map-legend-panel .list-group .list-group-item:not(.h4,.h5,.h6):hover { + background-color: var(--bs-list-group-action-hover-bg); +} .popover { --bs-popover-header-padding-x: .75rem; |