| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  | import { Store, UIEventSource } from "../../Logic/UIEventSource" | 
					
						
							|  |  |  | import type { Map as MLMap } from "maplibre-gl" | 
					
						
							| 
									
										
										
										
											2023-04-21 01:53:24 +02:00
										 |  |  | import { Map as MlMap, SourceSpecification } from "maplibre-gl" | 
					
						
							| 
									
										
										
										
											2023-04-21 16:19:36 +02:00
										 |  |  | import { RasterLayerPolygon } from "../../Models/RasterLayers" | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  | import { Utils } from "../../Utils" | 
					
						
							| 
									
										
										
										
											2023-03-23 00:58:21 +01:00
										 |  |  | import { BBox } from "../../Logic/BBox" | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  | import { ExportableMap, MapProperties } from "../../Models/MapProperties" | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  | import SvelteUIElement from "../Base/SvelteUIElement" | 
					
						
							|  |  |  | import MaplibreMap from "./MaplibreMap.svelte" | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  | import html2canvas from "html2canvas" | 
					
						
							| 
									
										
										
										
											2023-04-21 16:19:36 +02:00
										 |  |  | import { RasterLayerProperties } from "../../Models/RasterLayerProperties" | 
					
						
							| 
									
										
										
										
											2023-03-23 00:58:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  | /** | 
					
						
							|  |  |  |  * The 'MapLibreAdaptor' bridges 'MapLibre' with the various properties of the `MapProperties` | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  | export class MapLibreAdaptor implements MapProperties, ExportableMap { | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |     private static maplibre_control_handlers = [ | 
					
						
							| 
									
										
										
										
											2023-03-25 02:48:24 +01:00
										 |  |  |         // "scrollZoom",
 | 
					
						
							|  |  |  |         // "boxZoom",
 | 
					
						
							|  |  |  |         // "doubleClickZoom",
 | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |         "dragRotate", | 
					
						
							|  |  |  |         "dragPan", | 
					
						
							|  |  |  |         "keyboard", | 
					
						
							|  |  |  |         "touchZoomRotate", | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |     private static maplibre_zoom_handlers = [ | 
					
						
							|  |  |  |         "scrollZoom", | 
					
						
							|  |  |  |         "boxZoom", | 
					
						
							|  |  |  |         "doubleClickZoom", | 
					
						
							|  |  |  |         "touchZoomRotate", | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2023-03-23 00:58:21 +01:00
										 |  |  |     readonly location: UIEventSource<{ lon: number; lat: number }> | 
					
						
							|  |  |  |     readonly zoom: UIEventSource<number> | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |     readonly bounds: UIEventSource<BBox> | 
					
						
							| 
									
										
										
										
											2023-03-23 00:58:21 +01:00
										 |  |  |     readonly rasterLayer: UIEventSource<RasterLayerPolygon | undefined> | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |     readonly maxbounds: UIEventSource<BBox | undefined> | 
					
						
							|  |  |  |     readonly allowMoving: UIEventSource<true | boolean | undefined> | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |     readonly allowZooming: UIEventSource<true | boolean | undefined> | 
					
						
							|  |  |  |     readonly lastClickLocation: Store<undefined | { lon: number; lat: number }> | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |     readonly minzoom: UIEventSource<number> | 
					
						
							| 
									
										
										
										
											2023-04-21 01:53:24 +02:00
										 |  |  |     readonly maxzoom: UIEventSource<number> | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |     private readonly _maplibreMap: Store<MLMap> | 
					
						
							| 
									
										
										
										
											2023-03-23 00:58:21 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Used for internal bookkeeping (to remove a rasterLayer when done loading) | 
					
						
							|  |  |  |      * @private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private _currentRasterLayer: string | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  |     constructor(maplibreMap: Store<MLMap>, state?: Partial<MapProperties>) { | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |         this._maplibreMap = maplibreMap | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-23 00:58:21 +01:00
										 |  |  |         this.location = state?.location ?? new UIEventSource({ lon: 0, lat: 0 }) | 
					
						
							|  |  |  |         this.zoom = state?.zoom ?? new UIEventSource(1) | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |         this.minzoom = state?.minzoom ?? new UIEventSource(0) | 
					
						
							| 
									
										
										
										
											2023-04-21 01:53:24 +02:00
										 |  |  |         this.maxzoom = state?.maxzoom ?? new UIEventSource(24) | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |         this.zoom.addCallbackAndRunD((z) => { | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |             if (z < this.minzoom.data) { | 
					
						
							|  |  |  |                 this.zoom.setData(this.minzoom.data) | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2023-04-21 01:53:24 +02:00
										 |  |  |             const max = Math.min(24, this.maxzoom.data ?? 24) | 
					
						
							|  |  |  |             if (z > max) { | 
					
						
							|  |  |  |                 this.zoom.setData(max) | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         this.maxbounds = state?.maxbounds ?? new UIEventSource(undefined) | 
					
						
							|  |  |  |         this.allowMoving = state?.allowMoving ?? new UIEventSource(true) | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |         this.allowZooming = state?.allowZooming ?? new UIEventSource(true) | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |         this.bounds = state?.bounds ?? new UIEventSource(undefined) | 
					
						
							| 
									
										
										
										
											2023-03-23 00:58:21 +01:00
										 |  |  |         this.rasterLayer = | 
					
						
							|  |  |  |             state?.rasterLayer ?? new UIEventSource<RasterLayerPolygon | undefined>(undefined) | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |         const lastClickLocation = new UIEventSource<{ lon: number; lat: number }>(undefined) | 
					
						
							|  |  |  |         this.lastClickLocation = lastClickLocation | 
					
						
							| 
									
										
										
										
											2023-03-23 00:58:21 +01:00
										 |  |  |         const self = this | 
					
						
							| 
									
										
										
										
											2023-04-16 03:42:26 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         function handleClick(e) { | 
					
						
							|  |  |  |             if (e.originalEvent["consumed"]) { | 
					
						
							|  |  |  |                 // Workaround, 'ShowPointLayer' sets this flag
 | 
					
						
							|  |  |  |                 return | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             console.log(e) | 
					
						
							|  |  |  |             const lon = e.lngLat.lng | 
					
						
							|  |  |  |             const lat = e.lngLat.lat | 
					
						
							|  |  |  |             lastClickLocation.setData({ lon, lat }) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |         maplibreMap.addCallbackAndRunD((map) => { | 
					
						
							|  |  |  |             map.on("load", () => { | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |                 this.updateStores() | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |                 self.setBackground() | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |                 self.MoveMapToCurrentLoc(self.location.data) | 
					
						
							|  |  |  |                 self.SetZoom(self.zoom.data) | 
					
						
							|  |  |  |                 self.setMaxBounds(self.maxbounds.data) | 
					
						
							|  |  |  |                 self.setAllowMoving(self.allowMoving.data) | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |                 self.setAllowZooming(self.allowZooming.data) | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |                 self.setMinzoom(self.minzoom.data) | 
					
						
							| 
									
										
										
										
											2023-04-21 01:53:24 +02:00
										 |  |  |                 self.setMaxzoom(self.maxzoom.data) | 
					
						
							| 
									
										
										
										
											2023-04-20 01:52:23 +02:00
										 |  |  |                 self.setBounds(self.bounds.data) | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |             }) | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |             self.MoveMapToCurrentLoc(self.location.data) | 
					
						
							|  |  |  |             self.SetZoom(self.zoom.data) | 
					
						
							|  |  |  |             self.setMaxBounds(self.maxbounds.data) | 
					
						
							|  |  |  |             self.setAllowMoving(self.allowMoving.data) | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |             self.setAllowZooming(self.allowZooming.data) | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |             self.setMinzoom(self.minzoom.data) | 
					
						
							| 
									
										
										
										
											2023-04-21 01:53:24 +02:00
										 |  |  |             self.setMaxzoom(self.maxzoom.data) | 
					
						
							| 
									
										
										
										
											2023-04-20 01:52:23 +02:00
										 |  |  |             self.setBounds(self.bounds.data) | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |             this.updateStores() | 
					
						
							|  |  |  |             map.on("moveend", () => this.updateStores()) | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |             map.on("click", (e) => { | 
					
						
							| 
									
										
										
										
											2023-04-16 03:42:26 +02:00
										 |  |  |                 handleClick(e) | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |             map.on("contextmenu", (e) => { | 
					
						
							|  |  |  |                 handleClick(e) | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |             map.on("dblclick", (e) => { | 
					
						
							|  |  |  |                 handleClick(e) | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |             }) | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-23 00:58:21 +01:00
										 |  |  |         this.rasterLayer.addCallback((_) => | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |             self.setBackground().catch((_) => { | 
					
						
							| 
									
										
										
										
											2023-03-23 00:58:21 +01:00
										 |  |  |                 console.error("Could not set background") | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.location.addCallbackAndRunD((loc) => { | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |             self.MoveMapToCurrentLoc(loc) | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2023-03-23 00:58:21 +01:00
										 |  |  |         this.zoom.addCallbackAndRunD((z) => self.SetZoom(z)) | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |         this.maxbounds.addCallbackAndRun((bbox) => self.setMaxBounds(bbox)) | 
					
						
							|  |  |  |         this.allowMoving.addCallbackAndRun((allowMoving) => self.setAllowMoving(allowMoving)) | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |         this.allowZooming.addCallbackAndRun((allowZooming) => self.setAllowZooming(allowZooming)) | 
					
						
							|  |  |  |         this.bounds.addCallbackAndRunD((bounds) => self.setBounds(bounds)) | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-23 00:58:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Convenience constructor | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public static construct(): { | 
					
						
							|  |  |  |         map: Store<MLMap> | 
					
						
							|  |  |  |         ui: SvelteUIElement | 
					
						
							|  |  |  |         mapproperties: MapProperties | 
					
						
							|  |  |  |     } { | 
					
						
							|  |  |  |         const mlmap = new UIEventSource<MlMap>(undefined) | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |             map: mlmap, | 
					
						
							|  |  |  |             ui: new SvelteUIElement(MaplibreMap, { | 
					
						
							|  |  |  |                 map: mlmap, | 
					
						
							|  |  |  |             }), | 
					
						
							|  |  |  |             mapproperties: new MapLibreAdaptor(mlmap), | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-21 01:53:24 +02:00
										 |  |  |     public static prepareWmsSource(layer: RasterLayerProperties): SourceSpecification { | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |             type: "raster", | 
					
						
							|  |  |  |             // use the tiles option to specify a 256WMS tile source URL
 | 
					
						
							|  |  |  |             // https://maplibre.org/maplibre-gl-js-docs/style-spec/sources/
 | 
					
						
							|  |  |  |             tiles: [MapLibreAdaptor.prepareWmsURL(layer.url, layer["tile-size"] ?? 256)], | 
					
						
							|  |  |  |             tileSize: layer["tile-size"] ?? 256, | 
					
						
							|  |  |  |             minzoom: layer["min_zoom"] ?? 1, | 
					
						
							|  |  |  |             maxzoom: layer["max_zoom"] ?? 25, | 
					
						
							|  |  |  |             //  scheme: background["type"] === "tms" ? "tms" : "xyz",
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Prepares an ELI-URL to be compatible with mapbox | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2023-04-21 01:53:24 +02:00
										 |  |  |     private static prepareWmsURL(url: string, size: number = 256): string { | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |         // ELI:  LAYERS=OGWRGB13_15VL&STYLES=&FORMAT=image/jpeg&CRS={proj}&WIDTH={width}&HEIGHT={height}&BBOX={bbox}&VERSION=1.3.0&SERVICE=WMS&REQUEST=GetMap
 | 
					
						
							|  |  |  |         // PROD: SERVICE=WMS&REQUEST=GetMap&LAYERS=OGWRGB13_15VL&STYLES=&FORMAT=image/jpeg&TRANSPARENT=false&VERSION=1.3.0&WIDTH=256&HEIGHT=256&CRS=EPSG:3857&BBOX=488585.4847988467,6590094.830634755,489196.9810251281,6590706.32686104
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const toReplace = { | 
					
						
							|  |  |  |             "{bbox}": "{bbox-epsg-3857}", | 
					
						
							|  |  |  |             "{proj}": "EPSG:3857", | 
					
						
							|  |  |  |             "{width}": "" + size, | 
					
						
							|  |  |  |             "{height}": "" + size, | 
					
						
							|  |  |  |             "{zoom}": "{z}", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (const key in toReplace) { | 
					
						
							|  |  |  |             url = url.replace(new RegExp(key), toReplace[key]) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const subdomains = url.match(/\{switch:([a-zA-Z0-9,]*)}/) | 
					
						
							|  |  |  |         if (subdomains !== null) { | 
					
						
							|  |  |  |             const options = subdomains[1].split(",") | 
					
						
							|  |  |  |             const option = options[Math.floor(Math.random() * options.length)] | 
					
						
							|  |  |  |             url = url.replace(subdomains[0], option) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return url | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  |     async exportAsPng(): Promise<Blob> { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         if (map === undefined) { | 
					
						
							|  |  |  |             return undefined | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         function setDPI(canvas, dpi) { | 
					
						
							|  |  |  |             // Set up CSS size.
 | 
					
						
							|  |  |  |             canvas.style.width = canvas.style.width || canvas.width + "px" | 
					
						
							|  |  |  |             canvas.style.height = canvas.style.height || canvas.height + "px" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Resize canvas and scale future draws.
 | 
					
						
							|  |  |  |             const scaleFactor = dpi / 96 | 
					
						
							|  |  |  |             canvas.width = Math.ceil(canvas.width * scaleFactor) | 
					
						
							|  |  |  |             canvas.height = Math.ceil(canvas.height * scaleFactor) | 
					
						
							|  |  |  |             const ctx = canvas.getContext("2d") | 
					
						
							|  |  |  |             ctx?.scale(scaleFactor, scaleFactor) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Total hack - see https://stackoverflow.com/questions/42483449/mapbox-gl-js-export-map-to-png-or-pdf
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const drawOn = document.createElement("canvas") | 
					
						
							|  |  |  |         drawOn.width = document.documentElement.clientWidth | 
					
						
							|  |  |  |         drawOn.height = document.documentElement.clientHeight | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         setDPI(drawOn, 4 * 96) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const destinationCtx = drawOn.getContext("2d") | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // First, we draw the maplibre-map onto the canvas. This does not export markers
 | 
					
						
							|  |  |  |             // Inspiration by https://github.com/mapbox/mapbox-gl-js/issues/2766
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const promise = new Promise<void>((resolve) => { | 
					
						
							|  |  |  |                 map.once("render", () => { | 
					
						
							|  |  |  |                     destinationCtx.drawImage(map.getCanvas(), 0, 0) | 
					
						
							|  |  |  |                     resolve() | 
					
						
							|  |  |  |                 }) | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             while (!map.isStyleLoaded()) { | 
					
						
							|  |  |  |                 console.log("Waiting to fully load the style...") | 
					
						
							|  |  |  |                 await Utils.waitFor(100) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             map.triggerRepaint() | 
					
						
							|  |  |  |             await promise | 
					
						
							|  |  |  |             // Reset the canvas width and height
 | 
					
						
							|  |  |  |             map.resize() | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // now, we draw the markers on top of the map
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             /* We use html2canvas for this, but disable the map canvas object itself: | 
					
						
							|  |  |  |              * it cannot deal with this canvas object. | 
					
						
							|  |  |  |              * | 
					
						
							|  |  |  |              * We also have to patch up a few more objects | 
					
						
							|  |  |  |              * */ | 
					
						
							|  |  |  |             const container = map.getCanvasContainer() | 
					
						
							|  |  |  |             const origHeight = container.style.height | 
					
						
							|  |  |  |             const origStyle = map.getCanvas().style.display | 
					
						
							|  |  |  |             try { | 
					
						
							|  |  |  |                 map.getCanvas().style.display = "none" | 
					
						
							|  |  |  |                 if (!container.style.height) { | 
					
						
							|  |  |  |                     container.style.height = document.documentElement.clientHeight + "px" | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-20 17:42:07 +02:00
										 |  |  |                 await html2canvas(map.getCanvasContainer(), { | 
					
						
							|  |  |  |                     backgroundColor: "#00000000", | 
					
						
							|  |  |  |                     canvas: drawOn, | 
					
						
							|  |  |  |                 }) | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  |             } catch (e) { | 
					
						
							|  |  |  |                 console.error(e) | 
					
						
							|  |  |  |             } finally { | 
					
						
							|  |  |  |                 map.getCanvas().style.display = origStyle | 
					
						
							|  |  |  |                 container.style.height = origHeight | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // At last, we return the actual blob
 | 
					
						
							|  |  |  |         return new Promise<Blob>((resolve) => drawOn.toBlob((data) => resolve(data))) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private updateStores() { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							| 
									
										
										
										
											2023-04-20 17:42:07 +02:00
										 |  |  |         if (!map) { | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const dt = this.location.data | 
					
						
							|  |  |  |         dt.lon = map.getCenter().lng | 
					
						
							|  |  |  |         dt.lat = map.getCenter().lat | 
					
						
							|  |  |  |         this.location.ping() | 
					
						
							|  |  |  |         this.zoom.setData(Math.round(map.getZoom() * 10) / 10) | 
					
						
							|  |  |  |         const bounds = map.getBounds() | 
					
						
							|  |  |  |         const bbox = new BBox([ | 
					
						
							|  |  |  |             [bounds.getEast(), bounds.getNorth()], | 
					
						
							|  |  |  |             [bounds.getWest(), bounds.getSouth()], | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  |         this.bounds.setData(bbox) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |     private SetZoom(z: number) { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         if (!map || z === undefined) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (Math.abs(map.getZoom() - z) > 0.01) { | 
					
						
							|  |  |  |             map.setZoom(z) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private MoveMapToCurrentLoc(loc: { lat: number; lon: number }) { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         if (!map || loc === undefined) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const center = map.getCenter() | 
					
						
							|  |  |  |         if (center.lng !== loc.lon || center.lat !== loc.lat) { | 
					
						
							|  |  |  |             map.setCenter({ lng: loc.lon, lat: loc.lat }) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |     private async awaitStyleIsLoaded(): Promise<void> { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         if (map === undefined) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |         while (!map?.isStyleLoaded()) { | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |             await Utils.waitFor(250) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private removeCurrentLayer(map: MLMap) { | 
					
						
							|  |  |  |         if (this._currentRasterLayer) { | 
					
						
							|  |  |  |             // hide the previous layer
 | 
					
						
							|  |  |  |             map.removeLayer(this._currentRasterLayer) | 
					
						
							|  |  |  |             map.removeSource(this._currentRasterLayer) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private async setBackground() { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         if (map === undefined) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-03-23 00:58:21 +01:00
										 |  |  |         const background: RasterLayerProperties = this.rasterLayer?.data?.properties | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |         if (background !== undefined && this._currentRasterLayer === background.id) { | 
					
						
							|  |  |  |             // already the correct background layer, nothing to do
 | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-04-21 17:37:50 +02:00
										 |  |  |         // await this.awaitStyleIsLoaded()
 | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-23 00:58:21 +01:00
										 |  |  |         if (background !== this.rasterLayer?.data?.properties) { | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |             // User selected another background in the meantime... abort
 | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (background !== undefined && this._currentRasterLayer === background.id) { | 
					
						
							|  |  |  |             // already the correct background layer, nothing to do
 | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |         if (!background?.url) { | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |             // no background to set
 | 
					
						
							|  |  |  |             this.removeCurrentLayer(map) | 
					
						
							|  |  |  |             this._currentRasterLayer = undefined | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-21 01:53:24 +02:00
										 |  |  |         map.addSource(background.id, MapLibreAdaptor.prepareWmsSource(background)) | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         map.addLayer( | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 id: background.id, | 
					
						
							|  |  |  |                 type: "raster", | 
					
						
							|  |  |  |                 source: background.id, | 
					
						
							|  |  |  |                 paint: {}, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             background.category === "osmbasedmap" || background.category === "map" | 
					
						
							|  |  |  |                 ? undefined | 
					
						
							|  |  |  |                 : "aeroway_fill" | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         await this.awaitStyleIsLoaded() | 
					
						
							|  |  |  |         this.removeCurrentLayer(map) | 
					
						
							|  |  |  |         this._currentRasterLayer = background?.id | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     private setMaxBounds(bbox: undefined | BBox) { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         if (map === undefined) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (bbox) { | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |             map?.setMaxBounds(bbox.toLngLat()) | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |             map?.setMaxBounds(null) | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private setAllowMoving(allow: true | boolean | undefined) { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         if (map === undefined) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (allow === false) { | 
					
						
							|  |  |  |             for (const id of MapLibreAdaptor.maplibre_control_handlers) { | 
					
						
							|  |  |  |                 map[id].disable() | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             for (const id of MapLibreAdaptor.maplibre_control_handlers) { | 
					
						
							|  |  |  |                 map[id].enable() | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |     private setMinzoom(minzoom: number) { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         if (map === undefined) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         map.setMinZoom(minzoom) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-21 01:53:24 +02:00
										 |  |  |     private setMaxzoom(maxzoom: number) { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         if (map === undefined) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         map.setMaxZoom(maxzoom) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |     private setAllowZooming(allow: true | boolean | undefined) { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         if (map === undefined) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (allow === false) { | 
					
						
							|  |  |  |             for (const id of MapLibreAdaptor.maplibre_zoom_handlers) { | 
					
						
							|  |  |  |                 map[id].disable() | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             for (const id of MapLibreAdaptor.maplibre_zoom_handlers) { | 
					
						
							|  |  |  |                 map[id].enable() | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private setBounds(bounds: BBox) { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							| 
									
										
										
										
											2023-04-20 01:52:23 +02:00
										 |  |  |         if (map === undefined || bounds === undefined) { | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const oldBounds = map.getBounds() | 
					
						
							|  |  |  |         const e = 0.0000001 | 
					
						
							|  |  |  |         const hasDiff = | 
					
						
							|  |  |  |             Math.abs(oldBounds.getWest() - bounds.getWest()) > e && | 
					
						
							|  |  |  |             Math.abs(oldBounds.getEast() - bounds.getEast()) > e && | 
					
						
							|  |  |  |             Math.abs(oldBounds.getNorth() - bounds.getNorth()) > e && | 
					
						
							|  |  |  |             Math.abs(oldBounds.getSouth() - bounds.getSouth()) > e | 
					
						
							|  |  |  |         if (!hasDiff) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         map.fitBounds(bounds.toLngLat()) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  | } |