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>
							 |