| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  | <script lang="ts"> | 
					
						
							|  |  |  |   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"; | 
					
						
							|  |  |  |   import ToSvelte from "../../Base/ToSvelte.svelte"; | 
					
						
							|  |  |  |   import Svg from "../../../Svg.js"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											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-04-16 03:42:26 +02:00
										 |  |  |   export let value: UIEventSource<undefined | string>; | 
					
						
							| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  |   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); | 
					
						
							|  |  |  |   mla.allowMoving.setData(false) | 
					
						
							|  |  |  |   mla.allowZooming.setData(false) | 
					
						
							|  |  |  |   let directionElem: HTMLElement | undefined; | 
					
						
							|  |  |  |   $: value.addCallbackAndRunD(degrees => { | 
					
						
							|  |  |  |     if (directionElem === undefined) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     directionElem.style.rotate = degrees + "deg"; | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   let mainElem : HTMLElement | 
					
						
							|  |  |  |   function onPosChange(x: number, y: number) { | 
					
						
							|  |  |  |     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); | 
					
						
							| 
									
										
										
										
											2023-04-16 03:42:26 +02:00
										 |  |  |     value.setData(""+angleGeo); | 
					
						
							| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   let isDown = false; | 
					
						
							|  |  |  | </script> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <div bind:this={mainElem} class="relative w-48 h-48 cursor-pointer overflow-hidden" | 
					
						
							|  |  |  |      on:click={e => onPosChange(e.x, e.y)} | 
					
						
							|  |  |  |      on:mousedown={e => { | 
					
						
							|  |  |  |          isDown = true | 
					
						
							|  |  |  |          onPosChange(e.clientX, e.clientY) | 
					
						
							|  |  |  |        } } | 
					
						
							|  |  |  |      on:mousemove={e => { | 
					
						
							|  |  |  |       if(isDown){ | 
					
						
							|  |  |  |       onPosChange(e.clientX, e.clientY) | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |       }}} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      on:mouseup={() => { | 
					
						
							|  |  |  |          isDown = false | 
					
						
							|  |  |  |        } } | 
					
						
							|  |  |  |      on:touchmove={e => onPosChange(e.touches[0].clientX, e.touches[0].clientY)} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      on:touchstart={e => onPosChange(e.touches[0].clientX, e.touches[0].clientY)}> | 
					
						
							|  |  |  |   <div class="w-full h-full absolute top-0 left-0 cursor-pointer"> | 
					
						
							|  |  |  |     <MaplibreMap {map} attribution={false}></MaplibreMap> | 
					
						
							|  |  |  |   </div> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-16 03:42:26 +02:00
										 |  |  |   <div bind:this={directionElem} class="absolute w-full h-full top-0 left-0"> | 
					
						
							| 
									
										
										
										
											2023-03-29 17:21:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     <ToSvelte construct={ Svg.direction_stroke_svg}> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     </ToSvelte> | 
					
						
							|  |  |  |   </div> | 
					
						
							|  |  |  | </div> |