| 
									
										
										
										
											2024-02-03 14:33:10 +01:00
										 |  |  | import { ImmutableStore, Store, UIEventSource } from "../../Logic/UIEventSource" | 
					
						
							| 
									
										
										
										
											2023-10-16 14:27:05 +02:00
										 |  |  | import type { Map as MLMap } from "maplibre-gl" | 
					
						
							|  |  |  | import { Map as MlMap, SourceSpecification } from "maplibre-gl" | 
					
						
							| 
									
										
										
										
											2024-02-03 14:33:10 +01:00
										 |  |  | import { RasterLayerPolygon } from "../../Models/RasterLayers" | 
					
						
							| 
									
										
										
										
											2023-10-16 14:27:05 +02:00
										 |  |  | import { Utils } from "../../Utils" | 
					
						
							|  |  |  | import { BBox } from "../../Logic/BBox" | 
					
						
							| 
									
										
										
										
											2023-12-15 01:46:01 +01:00
										 |  |  | import { ExportableMap, KeyNavigationEvent, MapProperties } from "../../Models/MapProperties" | 
					
						
							| 
									
										
										
										
											2023-10-16 14:27:05 +02:00
										 |  |  | import SvelteUIElement from "../Base/SvelteUIElement" | 
					
						
							|  |  |  | import MaplibreMap from "./MaplibreMap.svelte" | 
					
						
							|  |  |  | import { RasterLayerProperties } from "../../Models/RasterLayerProperties" | 
					
						
							|  |  |  | import * as htmltoimage from "html-to-image" | 
					
						
							| 
									
										
										
										
											2024-01-28 00:04:24 +01:00
										 |  |  | import RasterLayerHandler from "./RasterLayerHandler" | 
					
						
							| 
									
										
										
										
											2024-02-03 14:33:10 +01:00
										 |  |  | import Constants from "../../Models/Constants" | 
					
						
							| 
									
										
										
										
											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-07-18 01:26:04 +02:00
										 |  |  |     readonly allowRotating: 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-12-19 22:21:34 +01:00
										 |  |  |     readonly rotation: UIEventSource<number> | 
					
						
							| 
									
										
										
										
											2024-02-03 14:33:10 +01:00
										 |  |  |     readonly pitch: UIEventSource<number> | 
					
						
							|  |  |  |     readonly useTerrain: Store<boolean> | 
					
						
							| 
									
										
										
										
											2023-12-15 01:46:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-16 03:32:04 +01:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2023-12-15 01:46:01 +01:00
										 |  |  |      * Functions that are called when one of those actions has happened | 
					
						
							|  |  |  |      * @private | 
					
						
							| 
									
										
										
										
											2023-11-16 03:32:04 +01:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2023-12-15 01:46:01 +01:00
										 |  |  |     private _onKeyNavigation: ((event: KeyNavigationEvent) => void | boolean)[] = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |     private readonly _maplibreMap: Store<MLMap> | 
					
						
							| 
									
										
										
										
											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-06-07 22:46:41 +02:00
										 |  |  |         this.location = state?.location ?? new UIEventSource(undefined) | 
					
						
							| 
									
										
										
										
											2023-06-04 00:43:32 +02:00
										 |  |  |         if (this.location.data) { | 
					
						
							| 
									
										
										
										
											2023-05-19 10:56:30 +02:00
										 |  |  |             // The MapLibre adaptor updates the element in the location and then pings them
 | 
					
						
							|  |  |  |             // Often, code setting this up doesn't expect the object they pass in to be changed, so we create a copy
 | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |             this.location.setData({ ...this.location.data }) | 
					
						
							| 
									
										
										
										
											2023-05-19 10:56:30 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-03-23 00:58:21 +01:00
										 |  |  |         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-07-18 01:26:04 +02:00
										 |  |  |         this.allowRotating = state?.allowRotating ?? new UIEventSource<boolean>(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-12-19 22:21:34 +01:00
										 |  |  |         this.rotation = state?.rotation ?? new UIEventSource<number>(0) | 
					
						
							| 
									
										
										
										
											2024-02-03 14:33:10 +01:00
										 |  |  |         this.pitch = state?.pitch ?? new UIEventSource<number>(0) | 
					
						
							|  |  |  |         this.useTerrain = state?.useTerrain ?? new ImmutableStore<boolean>(false) | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-28 00:04:24 +01:00
										 |  |  |         const rasterLayerHandler = new RasterLayerHandler(this._maplibreMap, this.rasterLayer) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-16 03:42:26 +02:00
										 |  |  |         function handleClick(e) { | 
					
						
							|  |  |  |             if (e.originalEvent["consumed"]) { | 
					
						
							|  |  |  |                 // Workaround, 'ShowPointLayer' sets this flag
 | 
					
						
							|  |  |  |                 return | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             const lon = e.lngLat.lng | 
					
						
							|  |  |  |             const lat = e.lngLat.lat | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |             lastClickLocation.setData({ lon, lat }) | 
					
						
							| 
									
										
										
										
											2023-04-16 03:42:26 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |         maplibreMap.addCallbackAndRunD((map) => { | 
					
						
							|  |  |  |             map.on("load", () => { | 
					
						
							| 
									
										
										
										
											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-07-18 01:26:04 +02:00
										 |  |  |                 self.setAllowRotating(self.allowRotating.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) | 
					
						
							| 
									
										
										
										
											2024-02-03 14:33:10 +01:00
										 |  |  |                 self.setTerrain(self.useTerrain.data) | 
					
						
							| 
									
										
										
										
											2024-01-28 00:04:24 +01:00
										 |  |  |                 rasterLayerHandler.setBackground() | 
					
						
							| 
									
										
										
										
											2023-05-18 23:42:03 +02:00
										 |  |  |                 this.updateStores(true) | 
					
						
							| 
									
										
										
										
											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-07-18 01:26:04 +02:00
										 |  |  |             self.setAllowRotating(self.allowRotating.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-12-19 22:21:34 +01:00
										 |  |  |             self.SetRotation(self.rotation.data) | 
					
						
							| 
									
										
										
										
											2024-02-03 14:33:10 +01:00
										 |  |  |             self.setTerrain(self.useTerrain.data) | 
					
						
							| 
									
										
										
										
											2024-01-28 00:04:24 +01:00
										 |  |  |             rasterLayerHandler.setBackground() | 
					
						
							| 
									
										
										
										
											2023-05-18 23:42:03 +02:00
										 |  |  |             this.updateStores(true) | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |             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
										 |  |  |             }) | 
					
						
							| 
									
										
										
										
											2024-01-24 23:45:20 +01:00
										 |  |  |             map.on("rotateend", (_) => { | 
					
						
							| 
									
										
										
										
											2023-12-19 22:21:34 +01:00
										 |  |  |                 this.updateStores() | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2024-02-03 14:33:10 +01:00
										 |  |  |             map.on("pitchend", () => { | 
					
						
							|  |  |  |                 this.updateStores() | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2023-11-16 03:32:04 +01:00
										 |  |  |             map.getContainer().addEventListener("keydown", (event) => { | 
					
						
							| 
									
										
										
										
											2023-12-15 01:46:01 +01:00
										 |  |  |                 let locked: "islocked" = undefined | 
					
						
							|  |  |  |                 if (!this.allowMoving.data) { | 
					
						
							|  |  |  |                     locked = "islocked" | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 switch (event.key) { | 
					
						
							|  |  |  |                     case "ArrowUp": | 
					
						
							|  |  |  |                         this.pingKeycodeEvent(locked ?? "north") | 
					
						
							|  |  |  |                         break | 
					
						
							|  |  |  |                     case "ArrowRight": | 
					
						
							|  |  |  |                         this.pingKeycodeEvent(locked ?? "east") | 
					
						
							|  |  |  |                         break | 
					
						
							|  |  |  |                     case "ArrowDown": | 
					
						
							|  |  |  |                         this.pingKeycodeEvent(locked ?? "south") | 
					
						
							|  |  |  |                         break | 
					
						
							|  |  |  |                     case "ArrowLeft": | 
					
						
							|  |  |  |                         this.pingKeycodeEvent(locked ?? "west") | 
					
						
							|  |  |  |                         break | 
					
						
							|  |  |  |                     case "+": | 
					
						
							|  |  |  |                         this.pingKeycodeEvent("in") | 
					
						
							|  |  |  |                         break | 
					
						
							|  |  |  |                     case "=": | 
					
						
							|  |  |  |                         this.pingKeycodeEvent("in") | 
					
						
							|  |  |  |                         break | 
					
						
							|  |  |  |                     case "-": | 
					
						
							|  |  |  |                         this.pingKeycodeEvent("out") | 
					
						
							|  |  |  |                         break | 
					
						
							| 
									
										
										
										
											2023-11-16 03:32:04 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-28 00:04:24 +01:00
										 |  |  |         this.rasterLayer.addCallbackAndRun((_) => rasterLayerHandler.setBackground()) | 
					
						
							| 
									
										
										
										
											2023-03-23 00:58:21 +01:00
										 |  |  |         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)) | 
					
						
							| 
									
										
										
										
											2023-12-19 22:21:34 +01:00
										 |  |  |         this.rotation.addCallbackAndRunD((bearing) => self.SetRotation(bearing)) | 
					
						
							| 
									
										
										
										
											2023-12-15 01:46:01 +01:00
										 |  |  |         this.allowMoving.addCallbackAndRun((allowMoving) => { | 
					
						
							|  |  |  |             self.setAllowMoving(allowMoving) | 
					
						
							|  |  |  |             self.pingKeycodeEvent(allowMoving ? "unlocked" : "locked") | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2023-07-18 01:26:04 +02:00
										 |  |  |         this.allowRotating.addCallbackAndRunD((allowRotating) => | 
					
						
							|  |  |  |             self.setAllowRotating(allowRotating) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |         this.allowZooming.addCallbackAndRun((allowZooming) => self.setAllowZooming(allowZooming)) | 
					
						
							|  |  |  |         this.bounds.addCallbackAndRunD((bounds) => self.setBounds(bounds)) | 
					
						
							| 
									
										
										
										
											2024-02-03 14:33:10 +01:00
										 |  |  |         this.useTerrain?.addCallbackAndRun(useTerrain => self.setTerrain(useTerrain)) | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							| 
									
										
										
										
											2024-01-28 00:04:24 +01:00
										 |  |  |         return RasterLayerHandler.prepareWmsSource(layer) | 
					
						
							| 
									
										
										
										
											2023-04-21 01:53:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Prepares an ELI-URL to be compatible with mapbox | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-14 16:14:27 +01:00
										 |  |  |     private static async toBlob(canvas: HTMLCanvasElement): Promise<Blob> { | 
					
						
							|  |  |  |         return await new Promise<Blob>((resolve) => canvas.toBlob((blob) => resolve(blob))) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private static async createImage(url: string): Promise<HTMLImageElement> { | 
					
						
							|  |  |  |         return new Promise((resolve, reject) => { | 
					
						
							|  |  |  |             const img = new Image() | 
					
						
							|  |  |  |             img.decode = () => resolve(img) as any | 
					
						
							|  |  |  |             img.onload = () => resolve(img) | 
					
						
							|  |  |  |             img.onerror = reject | 
					
						
							|  |  |  |             img.crossOrigin = "anonymous" | 
					
						
							|  |  |  |             img.decoding = "async" | 
					
						
							|  |  |  |             img.src = url | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-15 01:46:01 +01:00
										 |  |  |     public onKeyNavigationEvent(f: (event: KeyNavigationEvent) => void | boolean) { | 
					
						
							|  |  |  |         this._onKeyNavigation.push(f) | 
					
						
							|  |  |  |         return () => { | 
					
						
							|  |  |  |             this._onKeyNavigation.splice(this._onKeyNavigation.indexOf(f), 1) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-14 16:14:27 +01:00
										 |  |  |     public async exportAsPng( | 
					
						
							|  |  |  |         rescaleIcons: number = 1, | 
					
						
							|  |  |  |         progress: UIEventSource<{ current: number; total: number }> = undefined | 
					
						
							|  |  |  |     ): Promise<Blob> { | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  |         const map = this._maplibreMap.data | 
					
						
							| 
									
										
										
										
											2023-05-05 02:03:41 +02:00
										 |  |  |         if (!map) { | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  |             return undefined | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-11-14 16:14:27 +01:00
										 |  |  |         const drawOn = document.createElement("canvas", {}) | 
					
						
							| 
									
										
										
										
											2023-06-04 00:43:32 +02:00
										 |  |  |         const ctx = drawOn.getContext("2d") | 
					
						
							| 
									
										
										
										
											2023-11-14 16:14:27 +01:00
										 |  |  |         // The width/height has been set in 'mm' on the parent element and converted to pixels by the browser
 | 
					
						
							|  |  |  |         const w = map.getContainer().getBoundingClientRect().width | 
					
						
							|  |  |  |         const h = map.getContainer().getBoundingClientRect().height | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-03 14:33:10 +01:00
										 |  |  |         const dpi = map.getPixelRatio() | 
					
						
							| 
									
										
										
										
											2023-11-14 16:14:27 +01:00
										 |  |  |         // The 'css'-size stays constant...
 | 
					
						
							|  |  |  |         drawOn.style.width = w + "px" | 
					
						
							|  |  |  |         drawOn.style.height = h + "px" | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-14 16:14:27 +01:00
										 |  |  |         // ...but the number of pixels is increased
 | 
					
						
							|  |  |  |         drawOn.width = Math.ceil(w * dpi) | 
					
						
							|  |  |  |         drawOn.height = Math.ceil(h * dpi) | 
					
						
							| 
									
										
										
										
											2023-11-13 15:14:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-14 16:14:27 +01:00
										 |  |  |         await this.exportBackgroundOnCanvas(ctx) | 
					
						
							|  |  |  |         await this.drawMarkers(ctx, rescaleIcons, progress) | 
					
						
							|  |  |  |         return await MapLibreAdaptor.toBlob(drawOn) | 
					
						
							| 
									
										
										
										
											2023-06-04 00:43:32 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-15 01:46:01 +01:00
										 |  |  |     private pingKeycodeEvent( | 
					
						
							|  |  |  |         key: "north" | "east" | "south" | "west" | "in" | "out" | "islocked" | "locked" | "unlocked" | 
					
						
							|  |  |  |     ) { | 
					
						
							|  |  |  |         const event = { | 
					
						
							|  |  |  |             date: new Date(), | 
					
						
							|  |  |  |             key: key, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (let i = 0; i < this._onKeyNavigation.length; i++) { | 
					
						
							|  |  |  |             const f = this._onKeyNavigation[i] | 
					
						
							|  |  |  |             const unregister = f(event) | 
					
						
							|  |  |  |             if (unregister === true) { | 
					
						
							|  |  |  |                 this._onKeyNavigation.splice(i, 1) | 
					
						
							|  |  |  |                 i-- | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-04 00:43:32 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Exports the background map and lines to PNG. | 
					
						
							|  |  |  |      * Markers are _not_ rendered | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2023-06-04 22:52:13 +02:00
										 |  |  |     private async exportBackgroundOnCanvas(ctx: CanvasRenderingContext2D): Promise<void> { | 
					
						
							| 
									
										
										
										
											2023-06-04 00:43:32 +02:00
										 |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         // We draw the maplibre-map onto the canvas. This does not export markers
 | 
					
						
							|  |  |  |         // Inspiration by https://github.com/mapbox/mapbox-gl-js/issues/2766
 | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-04 00:43:32 +02:00
										 |  |  |         // Total hack - see https://stackoverflow.com/questions/42483449/mapbox-gl-js-export-map-to-png-or-pdf
 | 
					
						
							|  |  |  |         const promise = new Promise<void>((resolve) => { | 
					
						
							|  |  |  |             map.once("render", () => { | 
					
						
							|  |  |  |                 ctx.drawImage(map.getCanvas(), 0, 0) | 
					
						
							|  |  |  |                 resolve() | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  |             }) | 
					
						
							| 
									
										
										
										
											2023-06-04 00:43:32 +02:00
										 |  |  |         }) | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-04 00:43:32 +02:00
										 |  |  |         while (!map.isStyleLoaded()) { | 
					
						
							|  |  |  |             console.log("Waiting to fully load the style...") | 
					
						
							|  |  |  |             await Utils.waitFor(100) | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-06-04 00:43:32 +02:00
										 |  |  |         map.triggerRepaint() | 
					
						
							|  |  |  |         await promise | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-06 04:01:42 +01:00
										 |  |  |     private async drawElement( | 
					
						
							|  |  |  |         drawOn: CanvasRenderingContext2D, | 
					
						
							|  |  |  |         element: HTMLElement, | 
					
						
							|  |  |  |         rescaleIcons: number, | 
					
						
							|  |  |  |         pixelRatio: number | 
					
						
							|  |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2023-12-06 17:27:30 +01:00
										 |  |  |         const style = element.style.transform | 
					
						
							|  |  |  |         let x = element.getBoundingClientRect().x | 
					
						
							|  |  |  |         let y = element.getBoundingClientRect().y | 
					
						
							|  |  |  |         element.style.transform = "" | 
					
						
							| 
									
										
										
										
											2023-12-06 04:01:42 +01:00
										 |  |  |         const offset = style.match(/translate\(([-0-9]+)%, ?([-0-9]+)%\)/) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-06 17:27:30 +01:00
										 |  |  |         const w = element.style.width | 
					
						
							|  |  |  |         const h = element.style.height | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-06 04:01:42 +01:00
										 |  |  |         // Force a wider view for icon badges
 | 
					
						
							| 
									
										
										
										
											2023-12-06 17:27:30 +01:00
										 |  |  |         element.style.width = element.getBoundingClientRect().width * 4 + "px" | 
					
						
							|  |  |  |         element.style.height = element.getBoundingClientRect().height + "px" | 
					
						
							|  |  |  |         const svgSource = await htmltoimage.toSvg(element) | 
					
						
							| 
									
										
										
										
											2023-12-06 04:01:42 +01:00
										 |  |  |         const img = await MapLibreAdaptor.createImage(svgSource) | 
					
						
							| 
									
										
										
										
											2023-12-06 17:27:30 +01:00
										 |  |  |         element.style.width = w | 
					
						
							|  |  |  |         element.style.height = h | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-06 04:01:42 +01:00
										 |  |  |         if (offset && rescaleIcons !== 1) { | 
					
						
							|  |  |  |             const [_, __, relYStr] = offset | 
					
						
							|  |  |  |             const relY = Number(relYStr) | 
					
						
							|  |  |  |             y += img.height * (relY / 100) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         x *= pixelRatio | 
					
						
							|  |  |  |         y *= pixelRatio | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             drawOn.drawImage(img, x, y, img.width * rescaleIcons, img.height * rescaleIcons) | 
					
						
							|  |  |  |         } catch (e) { | 
					
						
							|  |  |  |             console.log("Could not draw image because of", e) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-14 16:14:27 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Draws the markers of the current map on the specified canvas. | 
					
						
							|  |  |  |      * The DPIfactor is used to calculate the correct position, whereas 'rescaleIcons' can be used to make the icons smaller | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private async drawMarkers( | 
					
						
							|  |  |  |         drawOn: CanvasRenderingContext2D, | 
					
						
							|  |  |  |         rescaleIcons: number = 1, | 
					
						
							|  |  |  |         progress: UIEventSource<{ current: number; total: number }> | 
					
						
							|  |  |  |     ): Promise<void> { | 
					
						
							| 
									
										
										
										
											2023-06-04 00:43:32 +02:00
										 |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         if (!map) { | 
					
						
							| 
									
										
										
										
											2023-11-14 16:14:27 +01:00
										 |  |  |             console.error("There is no map to export from") | 
					
						
							| 
									
										
										
										
											2023-06-04 00:43:32 +02:00
										 |  |  |             return undefined | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-11-13 15:14:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const container = map.getContainer() | 
					
						
							| 
									
										
										
										
											2023-12-06 04:01:42 +01:00
										 |  |  |         const pixelRatio = map.getPixelRatio() | 
					
						
							| 
									
										
										
										
											2023-11-14 16:14:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-13 15:14:41 +01:00
										 |  |  |         function isDisplayed(el: Element) { | 
					
						
							|  |  |  |             const r1 = el.getBoundingClientRect() | 
					
						
							|  |  |  |             const r2 = container.getBoundingClientRect() | 
					
						
							|  |  |  |             return !( | 
					
						
							|  |  |  |                 r2.left > r1.right || | 
					
						
							|  |  |  |                 r2.right < r1.left || | 
					
						
							|  |  |  |                 r2.top > r1.bottom || | 
					
						
							|  |  |  |                 r2.bottom < r1.top | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-11-14 16:14:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-13 15:14:41 +01:00
										 |  |  |         const markers = Array.from(container.getElementsByClassName("marker")) | 
					
						
							|  |  |  |         for (let i = 0; i < markers.length; i++) { | 
					
						
							| 
									
										
										
										
											2023-11-14 16:14:27 +01:00
										 |  |  |             const marker = <HTMLElement>markers[i] | 
					
						
							| 
									
										
										
										
											2023-12-06 04:01:42 +01:00
										 |  |  |             const labels = Array.from(marker.getElementsByClassName("marker-label")) | 
					
						
							| 
									
										
										
										
											2023-11-14 16:14:27 +01:00
										 |  |  |             const style = marker.style.transform | 
					
						
							| 
									
										
										
										
											2023-12-06 04:01:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (isDisplayed(marker)) { | 
					
						
							|  |  |  |                 await this.drawElement(drawOn, marker, rescaleIcons, pixelRatio) | 
					
						
							| 
									
										
										
										
											2023-11-14 16:14:27 +01:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-06 04:01:42 +01:00
										 |  |  |             for (const label of labels) { | 
					
						
							|  |  |  |                 if (isDisplayed(label)) { | 
					
						
							|  |  |  |                     await this.drawElement(drawOn, <HTMLElement>label, rescaleIcons, pixelRatio) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2023-11-14 16:14:27 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (progress) { | 
					
						
							|  |  |  |                 progress.setData({ current: i, total: markers.length }) | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2023-12-06 04:01:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-14 16:14:27 +01:00
										 |  |  |             marker.style.transform = style | 
					
						
							| 
									
										
										
										
											2023-11-13 15:14:41 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 23:42:03 +02:00
										 |  |  |     private updateStores(isSetup: boolean = false): void { | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  |         const map = this._maplibreMap.data | 
					
						
							| 
									
										
										
										
											2023-04-20 17:42:07 +02:00
										 |  |  |         if (!map) { | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |         const { lng, lat } = map.getCenter() | 
					
						
							| 
									
										
										
										
											2023-06-07 22:46:41 +02:00
										 |  |  |         if (lng === 0 && lat === 0) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (this.location.data === undefined) { | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |             this.location.setData({ lon: lng, lat }) | 
					
						
							| 
									
										
										
										
											2023-06-07 22:46:41 +02:00
										 |  |  |         } else if (!isSetup) { | 
					
						
							| 
									
										
										
										
											2023-06-14 23:21:19 +02:00
										 |  |  |             const lon = map.getCenter().lng | 
					
						
							|  |  |  |             const lat = map.getCenter().lat | 
					
						
							|  |  |  |             this.location.setData({ lon, lat }) | 
					
						
							| 
									
										
										
										
											2023-05-18 23:42:03 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  |         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()], | 
					
						
							|  |  |  |         ]) | 
					
						
							| 
									
										
										
										
											2023-05-18 23:42:03 +02:00
										 |  |  |         if (this.bounds.data === undefined || !isSetup) { | 
					
						
							|  |  |  |             this.bounds.setData(bbox) | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-12-19 22:21:34 +01:00
										 |  |  |         this.rotation.setData(map.getBearing()) | 
					
						
							| 
									
										
										
										
											2024-02-03 14:33:10 +01:00
										 |  |  |         this.pitch.setData(map.getPitch()) | 
					
						
							| 
									
										
										
										
											2023-04-19 03:20:49 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 15:44:54 +02:00
										 |  |  |     private SetZoom(z: number): void { | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         if (!map || z === undefined) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (Math.abs(map.getZoom() - z) > 0.01) { | 
					
						
							|  |  |  |             map.setZoom(z) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-19 22:21:34 +01:00
										 |  |  |     private SetRotation(bearing: number): void { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         if (!map || bearing === undefined) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         map.rotateTo(bearing, { duration: 0 }) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 15:44:54 +02:00
										 |  |  |     private MoveMapToCurrentLoc(loc: { lat: number; lon: number }): void { | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         if (!map || loc === undefined) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const center = map.getCenter() | 
					
						
							|  |  |  |         if (center.lng !== loc.lon || center.lat !== loc.lat) { | 
					
						
							| 
									
										
										
										
											2023-07-08 01:21:11 +02:00
										 |  |  |             if (isNaN(loc.lon) || isNaN(loc.lat)) { | 
					
						
							|  |  |  |                 console.error("Got invalid lat or lon, not setting") | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 map.setCenter({ lng: loc.lon, lat: loc.lat }) | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-01 03:29:57 +01:00
										 |  |  |     public installCustomKeyboardHandler(viewportStore: UIEventSource<HTMLDivElement>) { | 
					
						
							|  |  |  |         viewportStore.mapD( | 
					
						
							| 
									
										
										
										
											2023-12-22 18:50:22 +01:00
										 |  |  |             (viewport) => { | 
					
						
							|  |  |  |                 const map = this._maplibreMap.data | 
					
						
							|  |  |  |                 if (!map) { | 
					
						
							|  |  |  |                     return | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 const oldKeyboard = map.keyboard | 
					
						
							| 
									
										
										
										
											2024-01-01 03:29:57 +01:00
										 |  |  |                 const w = viewport.getBoundingClientRect().width | 
					
						
							|  |  |  |                 if (w < 10) { | 
					
						
							|  |  |  |                     /// this is weird, but definitively wrong!
 | 
					
						
							|  |  |  |                     console.log("Got a very small bound", w, viewport) | 
					
						
							|  |  |  |                     // We try again later on
 | 
					
						
							|  |  |  |                     window.requestAnimationFrame(() => { | 
					
						
							|  |  |  |                         viewportStore.ping() | 
					
						
							|  |  |  |                     }) | 
					
						
							|  |  |  |                     return | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 oldKeyboard._panStep = w | 
					
						
							| 
									
										
										
										
											2023-12-22 18:50:22 +01:00
										 |  |  |             }, | 
					
						
							|  |  |  |             [this._maplibreMap] | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     private setMaxBounds(bbox: undefined | BBox) { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							| 
									
										
										
										
											2023-05-05 02:03:41 +02:00
										 |  |  |         if (!map) { | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |             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
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 01:26:04 +02:00
										 |  |  |     private setAllowRotating(allow: true | boolean | undefined) { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         if (!map) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (allow === false) { | 
					
						
							|  |  |  |             map.rotateTo(0, { duration: 0 }) | 
					
						
							|  |  |  |             map.setPitch(0) | 
					
						
							|  |  |  |             map.dragRotate.disable() | 
					
						
							| 
									
										
										
										
											2023-12-15 01:46:01 +01:00
										 |  |  |             map.keyboard.disableRotation() | 
					
						
							| 
									
										
										
										
											2023-09-28 23:50:27 +02:00
										 |  |  |             map.touchZoomRotate.disableRotation() | 
					
						
							| 
									
										
										
										
											2023-07-18 01:26:04 +02:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             map.dragRotate.enable() | 
					
						
							| 
									
										
										
										
											2023-12-15 01:46:01 +01:00
										 |  |  |             map.keyboard.enableRotation() | 
					
						
							| 
									
										
										
										
											2023-09-28 23:50:27 +02:00
										 |  |  |             map.touchZoomRotate.enableRotation() | 
					
						
							| 
									
										
										
										
											2023-07-18 01:26:04 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |     private setAllowMoving(allow: true | boolean | undefined) { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							| 
									
										
										
										
											2023-05-05 02:03:41 +02:00
										 |  |  |         if (!map) { | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |             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-07-18 01:26:04 +02:00
										 |  |  |         this.setAllowRotating(this.allowRotating.data) | 
					
						
							| 
									
										
										
										
											2023-03-24 19:21:15 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2023-05-05 02:03:41 +02:00
										 |  |  |         if (!map) { | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         map.setMinZoom(minzoom) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-21 01:53:24 +02:00
										 |  |  |     private setMaxzoom(maxzoom: number) { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							| 
									
										
										
										
											2023-05-05 02:03:41 +02:00
										 |  |  |         if (!map) { | 
					
						
							| 
									
										
										
										
											2023-04-21 01:53:24 +02:00
										 |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         map.setMaxZoom(maxzoom) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |     private setAllowZooming(allow: true | boolean | undefined) { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							| 
									
										
										
										
											2023-05-05 02:03:41 +02:00
										 |  |  |         if (!map) { | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |             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-05-05 02:03:41 +02:00
										 |  |  |         if (!map || 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()) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-02-03 14:33:10 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     private async setTerrain(useTerrain: boolean) { | 
					
						
							|  |  |  |         const map = this._maplibreMap.data | 
					
						
							|  |  |  |         if (!map) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const id = "maptiler-terrain-data" | 
					
						
							|  |  |  |         if (useTerrain) { | 
					
						
							|  |  |  |             if(map.getTerrain()){ | 
					
						
							|  |  |  |                return | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             map.addSource(id, { | 
					
						
							|  |  |  |                 "type": "raster-dem", | 
					
						
							|  |  |  |                 "url": "https://api.maptiler.com/tiles/terrain-rgb/tiles.json?key=" + Constants.maptilerApiKey | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |             try{ | 
					
						
							|  |  |  |                 while (!map?.isStyleLoaded()) { | 
					
						
							|  |  |  |                     await Utils.waitFor(250) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             map.setTerrain({ | 
					
						
							|  |  |  |                 source: id | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |             }catch (e) { | 
					
						
							|  |  |  |                 console.error(e) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-11 02:37:07 +01:00
										 |  |  | } |