forked from MapComplete/MapComplete
		
	
		
			
	
	
		
			71 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			Svelte
		
	
	
	
	
	
		
		
			
		
	
	
			71 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			Svelte
		
	
	
	
	
	
|  | <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"; | ||
|  | 
 | ||
|  |   /** | ||
|  |    * A visualisation to pick a direction on a map background | ||
|  |    */ | ||
|  |   export let value: UIEventSource<undefined | number>; | ||
|  |   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 => { | ||
|  |     console.log("Degrees are", degrees, directionElem); | ||
|  |     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); | ||
|  |     value.setData(angleGeo); | ||
|  |   } | ||
|  | 
 | ||
|  |   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> | ||
|  | 
 | ||
|  |   <div bind:this={directionElem} class="absolute w-full h-full top-0 left-0 border border-red-500"> | ||
|  | 
 | ||
|  |     <ToSvelte construct={ Svg.direction_stroke_svg}> | ||
|  | 
 | ||
|  |     </ToSvelte> | ||
|  |   </div> | ||
|  | </div> |