| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import { InputElement } from "./InputElement" | 
					
						
							|  |  |  | import { UIEventSource } from "../../Logic/UIEventSource" | 
					
						
							|  |  |  | import Combine from "../Base/Combine" | 
					
						
							|  |  |  | import Svg from "../../Svg" | 
					
						
							|  |  |  | import { Utils } from "../../Utils" | 
					
						
							|  |  |  | import Loc from "../../Models/Loc" | 
					
						
							|  |  |  | import { GeoOperations } from "../../Logic/GeoOperations" | 
					
						
							|  |  |  | import Minimap, { MinimapObj } from "../Base/Minimap" | 
					
						
							|  |  |  | import BackgroundMapSwitch from "../BigComponents/BackgroundMapSwitch" | 
					
						
							|  |  |  | import BaseUIElement from "../BaseUIElement" | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Selects a length after clicking on the minimap, in meters | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | export default class LengthInput extends InputElement<string> { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private readonly _location: UIEventSource<Loc> | 
					
						
							|  |  |  |     private readonly value: UIEventSource<string> | 
					
						
							|  |  |  |     private readonly background: UIEventSource<any> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     constructor( | 
					
						
							|  |  |  |         mapBackground: UIEventSource<any>, | 
					
						
							|  |  |  |         location: UIEventSource<Loc>, | 
					
						
							|  |  |  |         value?: UIEventSource<string> | 
					
						
							|  |  |  |     ) { | 
					
						
							|  |  |  |         super() | 
					
						
							|  |  |  |         this._location = location | 
					
						
							|  |  |  |         this.value = value ?? new UIEventSource<string>(undefined) | 
					
						
							|  |  |  |         this.background = mapBackground | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |         this.SetClass("block") | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     GetValue(): UIEventSource<string> { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return this.value | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     IsValid(str: string): boolean { | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |         const t = Number(str) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return !isNaN(t) && t >= 0 | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     protected InnerConstructElement(): HTMLElement { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         let map: BaseUIElement & MinimapObj = undefined | 
					
						
							|  |  |  |         let layerControl: BaseUIElement = undefined | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |         if (!Utils.runningFromConsole) { | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |             map = Minimap.createMiniMap({ | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |                 background: this.background, | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |                 allowMoving: false, | 
					
						
							|  |  |  |                 location: this._location, | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |                 attribution: true, | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |                 leafletOptions: { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     tap: true, | 
					
						
							|  |  |  |                 }, | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |             }) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             layerControl = new BackgroundMapSwitch( | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     locationControl: this._location, | 
					
						
							|  |  |  |                     backgroundLayer: this.background, | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 this.background, | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     allowedCategories: ["map", "photo"], | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const crosshair = new Combine([ | 
					
						
							|  |  |  |             Svg.length_crosshair_svg().SetStyle( | 
					
						
							|  |  |  |                 `position: absolute;top: 0;left: 0;transform:rotate(${this.value.data ?? 0}deg);` | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  |             .SetClass("block length-crosshair-svg relative pointer-events-none") | 
					
						
							| 
									
										
										
										
											2022-06-19 19:10:56 +02:00
										 |  |  |             .SetStyle("z-index: 1000; visibility: hidden") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |         const element = new Combine([ | 
					
						
							| 
									
										
										
										
											2022-06-19 19:10:56 +02:00
										 |  |  |             crosshair, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             layerControl?.SetStyle( | 
					
						
							|  |  |  |                 "position: absolute; bottom: 0.25rem; left: 0.25rem; z-index: 1000" | 
					
						
							|  |  |  |             ), | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |             map?.SetClass("w-full h-full block absolute top-0 left-O overflow-hidden"), | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |         ]) | 
					
						
							| 
									
										
										
										
											2022-06-19 19:10:56 +02:00
										 |  |  |             .SetClass("relative block bg-white border border-black rounded-xl overflow-hidden") | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |             .ConstructElement() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this.RegisterTriggers( | 
					
						
							|  |  |  |             map?.ConstructElement(), | 
					
						
							|  |  |  |             map?.leafletMap, | 
					
						
							|  |  |  |             crosshair.ConstructElement() | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |         element.style.overflow = "hidden" | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |         element.style.display = "block" | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return element | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private RegisterTriggers( | 
					
						
							|  |  |  |         htmlElement: HTMLElement, | 
					
						
							|  |  |  |         leafletMap: UIEventSource<L.Map>, | 
					
						
							|  |  |  |         measurementCrosshair: HTMLElement | 
					
						
							|  |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |         let firstClickXY: [number, number] = undefined | 
					
						
							|  |  |  |         let lastClickXY: [number, number] = undefined | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const self = this | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         function onPosChange(x: number, y: number, isDown: boolean, isUp?: boolean) { | 
					
						
							|  |  |  |             if (x === undefined || y === undefined) { | 
					
						
							|  |  |  |                 // Touch end
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 firstClickXY = undefined | 
					
						
							|  |  |  |                 lastClickXY = undefined | 
					
						
							|  |  |  |                 return | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const rect = htmlElement.getBoundingClientRect() | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |             // From the central part of location
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const dx = x - rect.left | 
					
						
							|  |  |  |             const dy = y - rect.top | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |             if (isDown) { | 
					
						
							|  |  |  |                 if (lastClickXY === undefined && firstClickXY === undefined) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     firstClickXY = [dx, dy] | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |                 } else if (firstClickXY !== undefined && lastClickXY === undefined) { | 
					
						
							|  |  |  |                     lastClickXY = [dx, dy] | 
					
						
							|  |  |  |                 } else if (firstClickXY !== undefined && lastClickXY !== undefined) { | 
					
						
							|  |  |  |                     // we measure again
 | 
					
						
							|  |  |  |                     firstClickXY = [dx, dy] | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     lastClickXY = undefined | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-07-28 23:47:00 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (firstClickXY === undefined) { | 
					
						
							|  |  |  |                 measurementCrosshair.style.visibility = "hidden" | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 return | 
					
						
							| 
									
										
										
										
											2022-07-28 23:47:00 +02:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const distance = Math.sqrt( | 
					
						
							|  |  |  |                 (dy - firstClickXY[1]) * (dy - firstClickXY[1]) + | 
					
						
							|  |  |  |                     (dx - firstClickXY[0]) * (dx - firstClickXY[0]) | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |             if (isUp) { | 
					
						
							|  |  |  |                 if (distance > 15) { | 
					
						
							|  |  |  |                     lastClickXY = [dx, dy] | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else if (lastClickXY !== undefined) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 return | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-07-28 23:47:00 +02:00
										 |  |  |             measurementCrosshair.style.visibility = "unset" | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             measurementCrosshair.style.left = firstClickXY[0] + "px" | 
					
						
							| 
									
										
										
										
											2022-07-28 23:47:00 +02:00
										 |  |  |             measurementCrosshair.style.top = firstClickXY[1] + "px" | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const angle = (180 * Math.atan2(firstClickXY[1] - dy, firstClickXY[0] - dx)) / Math.PI | 
					
						
							| 
									
										
										
										
											2022-07-28 23:47:00 +02:00
										 |  |  |             const angleGeo = (angle + 270) % 360 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const measurementCrosshairInner: HTMLElement = <HTMLElement>( | 
					
						
							|  |  |  |                 measurementCrosshair.firstChild | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             measurementCrosshairInner.style.transform = `rotate(${angleGeo}deg)` | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             measurementCrosshairInner.style.width = distance * 2 + "px" | 
					
						
							| 
									
										
										
										
											2022-07-28 23:47:00 +02:00
										 |  |  |             measurementCrosshairInner.style.marginLeft = -distance + "px" | 
					
						
							|  |  |  |             measurementCrosshairInner.style.marginTop = -distance + "px" | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-28 23:47:00 +02:00
										 |  |  |             const leaflet = leafletMap?.data | 
					
						
							|  |  |  |             if (leaflet) { | 
					
						
							|  |  |  |                 const first = leaflet.layerPointToLatLng(firstClickXY) | 
					
						
							|  |  |  |                 const last = leaflet.layerPointToLatLng([dx, dy]) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 const geoDist = | 
					
						
							|  |  |  |                     Math.floor( | 
					
						
							|  |  |  |                         GeoOperations.distanceBetween( | 
					
						
							|  |  |  |                             [first.lng, first.lat], | 
					
						
							|  |  |  |                             [last.lng, last.lat] | 
					
						
							|  |  |  |                         ) * 10 | 
					
						
							|  |  |  |                     ) / 10 | 
					
						
							| 
									
										
										
										
											2022-07-28 23:47:00 +02:00
										 |  |  |                 self.value.setData("" + geoDist) | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |         htmlElement.ontouchstart = (ev: TouchEvent) => { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             onPosChange(ev.touches[0].clientX, ev.touches[0].clientY, true) | 
					
						
							|  |  |  |             ev.preventDefault() | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |         htmlElement.ontouchmove = (ev: TouchEvent) => { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             onPosChange(ev.touches[0].clientX, ev.touches[0].clientY, false) | 
					
						
							|  |  |  |             ev.preventDefault() | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |         htmlElement.ontouchend = (ev: TouchEvent) => { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             onPosChange(undefined, undefined, false, true) | 
					
						
							|  |  |  |             ev.preventDefault() | 
					
						
							| 
									
										
										
										
											2021-07-20 01:33:58 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         htmlElement.onmousedown = (ev: MouseEvent) => { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             onPosChange(ev.clientX, ev.clientY, true) | 
					
						
							|  |  |  |             ev.preventDefault() | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         htmlElement.onmouseup = (ev) => { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             onPosChange(ev.clientX, ev.clientY, false, true) | 
					
						
							|  |  |  |             ev.preventDefault() | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         htmlElement.onmousemove = (ev: MouseEvent) => { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             onPosChange(ev.clientX, ev.clientY, false) | 
					
						
							|  |  |  |             ev.preventDefault() | 
					
						
							| 
									
										
										
										
											2021-07-14 16:06:34 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | } |