| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  | <script lang="ts"> | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   import { UIEventSource } from "../../../Logic/UIEventSource" | 
					
						
							|  |  |  |   import type { MapProperties } from "../../../Models/MapProperties" | 
					
						
							|  |  |  |   import { Map as MlMap } from "maplibre-gl" | 
					
						
							|  |  |  |   import { MapLibreAdaptor } from "../../Map/MapLibreAdaptor" | 
					
						
							|  |  |  |   import MaplibreMap from "../../Map/MaplibreMap.svelte" | 
					
						
							| 
									
										
										
										
											2023-12-01 15:23:28 +01:00
										 |  |  |   import Direction_stroke from "../../../assets/svg/Direction_stroke.svelte" | 
					
						
							| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2023-04-16 03:42:26 +02:00
										 |  |  |    * A visualisation to pick a direction on a map background. | 
					
						
							| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   export let value: UIEventSource<undefined | string> | 
					
						
							|  |  |  |   export let mapProperties: Partial<MapProperties> & { | 
					
						
							|  |  |  |     readonly location: UIEventSource<{ lon: number; lat: number }> | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   let map: UIEventSource<MlMap> = new UIEventSource<MlMap>(undefined) | 
					
						
							|  |  |  |   let mla = new MapLibreAdaptor(map, mapProperties) | 
					
						
							| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  |   mla.allowMoving.setData(false) | 
					
						
							|  |  |  |   mla.allowZooming.setData(false) | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   let directionElem: HTMLElement | undefined | 
					
						
							|  |  |  |   $: value.addCallbackAndRunD((degrees) => { | 
					
						
							| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  |     if (directionElem === undefined) { | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |       return | 
					
						
							| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |     directionElem.style.rotate = degrees + "deg" | 
					
						
							|  |  |  |   }) | 
					
						
							| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   let mainElem: HTMLElement | 
					
						
							| 
									
										
										
										
											2024-01-22 03:42:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  |   function onPosChange(x: number, y: number) { | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |     const rect = mainElem.getBoundingClientRect() | 
					
						
							|  |  |  |     const dx = -(rect.left + rect.right) / 2 + x | 
					
						
							|  |  |  |     const dy = (rect.top + rect.bottom) / 2 - y | 
					
						
							|  |  |  |     const angle = (180 * Math.atan2(dy, dx)) / Math.PI | 
					
						
							|  |  |  |     const angleGeo = Math.floor((450 - angle) % 360) | 
					
						
							|  |  |  |     value.setData("" + angleGeo) | 
					
						
							| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   let isDown = false | 
					
						
							| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  | </script> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  | <div | 
					
						
							|  |  |  |   bind:this={mainElem} | 
					
						
							| 
									
										
										
										
											2023-06-14 20:44:01 +02:00
										 |  |  |   class="relative h-48 w-48 cursor-pointer overflow-hidden" | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   on:click={(e) => onPosChange(e.x, e.y)} | 
					
						
							|  |  |  |   on:mousedown={(e) => { | 
					
						
							|  |  |  |     isDown = true | 
					
						
							|  |  |  |     onPosChange(e.clientX, e.clientY) | 
					
						
							|  |  |  |   }} | 
					
						
							|  |  |  |   on:mousemove={(e) => { | 
					
						
							|  |  |  |     if (isDown) { | 
					
						
							| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  |       onPosChange(e.clientX, e.clientY) | 
					
						
							| 
									
										
										
										
											2023-06-18 00:48:28 +02:00
										 |  |  |       e.preventDefault() | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   }} | 
					
						
							|  |  |  |   on:mouseup={() => { | 
					
						
							|  |  |  |     isDown = false | 
					
						
							|  |  |  |   }} | 
					
						
							| 
									
										
										
										
											2023-07-15 19:28:59 +02:00
										 |  |  |   on:touchmove={(e) => { | 
					
						
							|  |  |  |     onPosChange(e.touches[0].clientX, e.touches[0].clientY) | 
					
						
							|  |  |  |     e.preventDefault() | 
					
						
							|  |  |  |   }} | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   on:touchstart={(e) => onPosChange(e.touches[0].clientX, e.touches[0].clientY)} | 
					
						
							|  |  |  | > | 
					
						
							| 
									
										
										
										
											2023-06-14 20:44:01 +02:00
										 |  |  |   <div class="absolute top-0 left-0 h-full w-full cursor-pointer"> | 
					
						
							| 
									
										
										
										
											2024-03-25 04:17:13 +01:00
										 |  |  |     <MaplibreMap mapProperties={mla} {map} /> | 
					
						
							| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  |   </div> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 20:44:01 +02:00
										 |  |  |   <div bind:this={directionElem} class="absolute top-0 left-0 h-full w-full"> | 
					
						
							| 
									
										
										
										
											2023-12-01 15:23:28 +01:00
										 |  |  |     <Direction_stroke /> | 
					
						
							| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  |   </div> | 
					
						
							|  |  |  | </div> |