forked from MapComplete/MapComplete
		
	Better compass arrow
This commit is contained in:
		
							parent
							
								
									ba47d1bfad
								
							
						
					
					
						commit
						82409984dc
					
				
					 15 changed files with 219 additions and 114 deletions
				
			
		|  | @ -1,9 +1,39 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||||
| <svg xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> | ||||
|     <g id="surface1"> | ||||
|         <path | ||||
|                 style="fill:#000000;" | ||||
|                 class="selectable" | ||||
|               d="M 375 187.5 C 375 291.054688 291.054688 375 187.5 375 C 83.945312 375 0 291.054688 0 187.5 C 0 83.945312 83.945312 0 187.5 0 C 291.054688 0 375 83.945312 375 187.5 Z M 375 187.5 "/> | ||||
|     </g> | ||||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <svg | ||||
|    width="375px" | ||||
|    height="375px" | ||||
|    viewBox="0 0 375 375" | ||||
|    version="1.1" | ||||
|    id="svg1" | ||||
|    sodipodi:docname="circle.svg" | ||||
|    inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg"> | ||||
|   <defs | ||||
|      id="defs1" /> | ||||
|   <sodipodi:namedview | ||||
|      id="namedview1" | ||||
|      pagecolor="#505050" | ||||
|      bordercolor="#eeeeee" | ||||
|      borderopacity="1" | ||||
|      inkscape:showpageshadow="0" | ||||
|      inkscape:pageopacity="0" | ||||
|      inkscape:pagecheckerboard="0" | ||||
|      inkscape:deskcolor="#d1d1d1" | ||||
|      inkscape:zoom="2.056" | ||||
|      inkscape:cx="187.5" | ||||
|      inkscape:cy="187.5" | ||||
|      inkscape:window-width="1920" | ||||
|      inkscape:window-height="995" | ||||
|      inkscape:window-x="0" | ||||
|      inkscape:window-y="0" | ||||
|      inkscape:window-maximized="1" | ||||
|      inkscape:current-layer="svg1" /> | ||||
|   <path | ||||
|      style="fill:#000000" | ||||
|      class="selectable" | ||||
|      d="M 375,187.5 C 375,291.05469 291.05469,375 187.5,375 83.945312,375 0,291.05469 0,187.5 0,83.945312 83.945312,0 187.5,0 291.05469,0 375,83.945312 375,187.5 Z m 0,0" | ||||
|      id="path1" /> | ||||
| </svg> | ||||
|  |  | |||
| Before Width: | Height: | Size: 486 B After Width: | Height: | Size: 1.2 KiB | 
							
								
								
									
										39
									
								
								assets/svg/compass_arrow.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								assets/svg/compass_arrow.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,39 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <svg | ||||
|    width="375px" | ||||
|    height="375px" | ||||
|    viewBox="0 0 375 375" | ||||
|    version="1.1" | ||||
|    id="svg1" | ||||
|    sodipodi:docname="compass_arrow.svg" | ||||
|    inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg"> | ||||
|   <defs | ||||
|      id="defs1" /> | ||||
|   <sodipodi:namedview | ||||
|      id="namedview1" | ||||
|      pagecolor="#505050" | ||||
|      bordercolor="#eeeeee" | ||||
|      borderopacity="1" | ||||
|      inkscape:showpageshadow="0" | ||||
|      inkscape:pageopacity="0" | ||||
|      inkscape:pagecheckerboard="0" | ||||
|      inkscape:deskcolor="#d1d1d1" | ||||
|      inkscape:zoom="1.0410569" | ||||
|      inkscape:cx="33.139398" | ||||
|      inkscape:cy="182.98711" | ||||
|      inkscape:window-width="1920" | ||||
|      inkscape:window-height="995" | ||||
|      inkscape:window-x="0" | ||||
|      inkscape:window-y="0" | ||||
|      inkscape:window-maximized="1" | ||||
|      inkscape:current-layer="svg1" /> | ||||
|   <path | ||||
|      id="rect2" | ||||
|      style="fill:#000000;stroke:none;stroke-linecap:round;fill-opacity:1;stroke-opacity:1" | ||||
|      d="M 16.835505,17.477497 79.869453,33.962116 V 80.511444 H 33.96212 Z" | ||||
|      sodipodi:nodetypes="ccccc" /> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 1.2 KiB | 
							
								
								
									
										2
									
								
								assets/svg/compass_arrow.svg.license
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								assets/svg/compass_arrow.svg.license
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | |||
| SPDX-FileCopyrightText: Pieter Vander Vennet | ||||
| SPDX-License-Identifier: CC0 | ||||
|  | @ -241,6 +241,14 @@ | |||
|     "authors": [], | ||||
|     "sources": [] | ||||
|   }, | ||||
|   { | ||||
|     "path": "compass_arrow.svg", | ||||
|     "license": "CC0-1.0", | ||||
|     "authors": [ | ||||
|       "Pieter Vander Vennet" | ||||
|     ], | ||||
|     "sources": [] | ||||
|   }, | ||||
|   { | ||||
|     "path": "confirm.svg", | ||||
|     "license": "CC0-1.0", | ||||
|  |  | |||
|  | @ -729,14 +729,6 @@ video { | |||
|   bottom: 0px; | ||||
| } | ||||
| 
 | ||||
| .top-1\/2 { | ||||
|   top: 50%; | ||||
| } | ||||
| 
 | ||||
| .left-1\/2 { | ||||
|   left: 50%; | ||||
| } | ||||
| 
 | ||||
| .right-4 { | ||||
|   right: 1rem; | ||||
| } | ||||
|  | @ -1126,10 +1118,6 @@ video { | |||
|   height: 0px; | ||||
| } | ||||
| 
 | ||||
| .h-5 { | ||||
|   height: 1.25rem; | ||||
| } | ||||
| 
 | ||||
| .h-4 { | ||||
|   height: 1rem; | ||||
| } | ||||
|  | @ -1150,6 +1138,10 @@ video { | |||
|   height: 2.75rem; | ||||
| } | ||||
| 
 | ||||
| .h-5 { | ||||
|   height: 1.25rem; | ||||
| } | ||||
| 
 | ||||
| .h-48 { | ||||
|   height: 12rem; | ||||
| } | ||||
|  | @ -1240,10 +1232,6 @@ video { | |||
|   width: 0px; | ||||
| } | ||||
| 
 | ||||
| .w-5 { | ||||
|   width: 1.25rem; | ||||
| } | ||||
| 
 | ||||
| .w-4 { | ||||
|   width: 1rem; | ||||
| } | ||||
|  | @ -1272,6 +1260,10 @@ video { | |||
|   width: auto; | ||||
| } | ||||
| 
 | ||||
| .w-5 { | ||||
|   width: 1.25rem; | ||||
| } | ||||
| 
 | ||||
| .w-10 { | ||||
|   width: 2.5rem; | ||||
| } | ||||
|  | @ -1346,10 +1338,6 @@ video { | |||
|   cursor: pointer; | ||||
| } | ||||
| 
 | ||||
| .cursor-wait { | ||||
|   cursor: wait; | ||||
| } | ||||
| 
 | ||||
| .resize { | ||||
|   resize: both; | ||||
| } | ||||
|  | @ -1745,11 +1733,6 @@ video { | |||
|   background-color: rgb(255 255 255 / var(--tw-bg-opacity)); | ||||
| } | ||||
| 
 | ||||
| .bg-red-500 { | ||||
|   --tw-bg-opacity: 1; | ||||
|   background-color: rgb(239 68 68 / var(--tw-bg-opacity)); | ||||
| } | ||||
| 
 | ||||
| .bg-white\/50 { | ||||
|   background-color: rgb(255 255 255 / 0.5); | ||||
| } | ||||
|  | @ -2756,6 +2739,18 @@ a.link-underline { | |||
|   overflow: visible !important; | ||||
| } | ||||
| 
 | ||||
| .compass_arrow { | ||||
|   width: calc( 2.5rem - 1px ) ; | ||||
|   height: calc( 2.5rem - 1px ) | ||||
| } | ||||
| 
 | ||||
| @media (min-width: 640px) { | ||||
|   .compass_arrow { | ||||
|     width: calc( 2.75rem - 1px ) ; | ||||
|     height: calc( 2.75rem - 1px ) | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @-webkit-keyframes glowing-drop-shadow { | ||||
|   from { | ||||
|     -webkit-filter: drop-shadow(5px 5px 60px rgb(128 128 128 / 0.6)); | ||||
|  | @ -2863,6 +2858,10 @@ a.link-underline { | |||
|     margin: 0.5rem; | ||||
|   } | ||||
| 
 | ||||
|   .sm\:m-1 { | ||||
|     margin: 0.25rem; | ||||
|   } | ||||
| 
 | ||||
|   .sm\:mx-1 { | ||||
|     margin-left: 0.25rem; | ||||
|     margin-right: 0.25rem; | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| import { UIEventSource } from "../UIEventSource" | ||||
| import { Stores, UIEventSource } from "../UIEventSource" | ||||
| 
 | ||||
| /** | ||||
|  * Exports the device orientation as UIEventSources and detects 'shakes' | ||||
|  | @ -33,8 +33,19 @@ export class Orientation { | |||
| 
 | ||||
|     constructor() {} | ||||
| 
 | ||||
|     public fakeMeasurements() { | ||||
|     public fakeMeasurements(rotateAlpha: boolean = true) { | ||||
|         console.log("Starting fake measurements of orientation sensors", { | ||||
|             alpha: this.alpha, | ||||
|             beta: this.beta, | ||||
|             gamma: this.gamma, | ||||
|             absolute: this.absolute, | ||||
|         }) | ||||
|         this.alpha.setData(45) | ||||
|         if (rotateAlpha) { | ||||
|             Stores.Chronic(25).addCallback((date) => | ||||
|                 this.alpha.setData(-(date.getTime() / 10) % 360) | ||||
|             ) | ||||
|         } | ||||
|         this.beta.setData(20) | ||||
|         this.gamma.setData(30) | ||||
|         this.absolute.setData(true) | ||||
|  |  | |||
|  | @ -60,6 +60,7 @@ import { Imgur } from "../Logic/ImageProviders/Imgur" | |||
| import NearbyFeatureSource from "../Logic/FeatureSource/Sources/NearbyFeatureSource" | ||||
| import FavouritesFeatureSource from "../Logic/FeatureSource/Sources/FavouritesFeatureSource" | ||||
| import { ProvidedImage } from "../Logic/ImageProviders/ImageProvider" | ||||
| import { GeolocationControlState } from "../UI/BigComponents/GeolocationControl" | ||||
| 
 | ||||
| /** | ||||
|  * | ||||
|  | @ -112,6 +113,8 @@ export default class ThemeViewState implements SpecialVisualizationState { | |||
|     readonly selectedLayer: UIEventSource<LayerConfig> | ||||
|     readonly userRelatedState: UserRelatedState | ||||
|     readonly geolocation: GeoLocationHandler | ||||
|     readonly geolocationControl: GeolocationControlState | ||||
| 
 | ||||
|     readonly lastGeolocationRequestMoment: UIEventSource<Date> = new UIEventSource<Date>(undefined) | ||||
| 
 | ||||
|     readonly imageUploadManager: ImageUploadManager | ||||
|  | @ -191,6 +194,7 @@ export default class ThemeViewState implements SpecialVisualizationState { | |||
|             this.mapProperties, | ||||
|             this.userRelatedState.gpsLocationHistoryRetentionTime | ||||
|         ) | ||||
|         this.geolocationControl = new GeolocationControlState(this.geolocation, this.mapProperties) | ||||
| 
 | ||||
|         this.availableLayers = AvailableRasterLayers.layersAvailableAt(this.mapProperties.location) | ||||
| 
 | ||||
|  | @ -591,6 +595,13 @@ export default class ThemeViewState implements SpecialVisualizationState { | |||
|                 Translations.t.hotkeyDocumentation.selectAerial, | ||||
|                 () => setLayerCategory("photo") | ||||
|             ) | ||||
|             Hotkeys.RegisterHotkey( | ||||
|                 { nomod: "L" }, | ||||
|                 Translations.t.hotkeyDocumentation.geolocate, | ||||
|                 () => { | ||||
|                     this.geolocationControl.handleClick() | ||||
|                 } | ||||
|             ) | ||||
|             return true | ||||
|         }) | ||||
|     } | ||||
|  |  | |||
|  | @ -12,11 +12,12 @@ | |||
|   export let arialabel: Translation = undefined  | ||||
| </script> | ||||
| 
 | ||||
|    | ||||
| <button | ||||
|   on:click={(e) => dispatch("click", e)} | ||||
|   on:keydown | ||||
|   use:ariaLabel={arialabel} | ||||
|   class={twJoin("pointer-events-auto h-fit w-fit rounded-full", cls)} | ||||
|   class={twJoin("relative pointer-events-auto h-fit w-fit rounded-full", cls)} | ||||
| > | ||||
|   <slot /> | ||||
| </button> | ||||
|  |  | |||
							
								
								
									
										44
									
								
								src/UI/BigComponents/GeolocationControl.svelte
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/UI/BigComponents/GeolocationControl.svelte
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | |||
| <script lang="ts"> | ||||
|   import Crosshair from "../../assets/svg/Crosshair.svelte" | ||||
|   import Location_refused from "../../assets/svg/Location_refused.svelte" | ||||
|   import { Store } from "../../Logic/UIEventSource.js" | ||||
|   import type { GeolocationPermissionState } from "../../Logic/State/GeoLocationState.js" | ||||
|   import ThemeViewState from "../../Models/ThemeViewState" | ||||
|   import Location_locked from "../../assets/svg/Location_locked.svelte" | ||||
|   import Location_unlocked from "../../assets/svg/Location_unlocked.svelte" | ||||
|   import Location from "../../assets/svg/Location.svelte" | ||||
| 
 | ||||
|   export let state: ThemeViewState | ||||
|   let geolocationstate = state.geolocation.geolocationState | ||||
|   let geopermission: Store<GeolocationPermissionState> = state.geolocation.geolocationState.permission | ||||
|   let allowMoving = geolocationstate.allowMoving | ||||
|   let currentGPSLocation = state.geolocation.geolocationState.currentGPSLocation | ||||
|   let geolocationControlState = state.geolocationControl | ||||
|   let lastClickWasRecent = geolocationControlState.lastClickWithinThreeSecs | ||||
| </script> | ||||
| 
 | ||||
| {#if !$allowMoving} | ||||
|   <Location_locked class="h-8 w-8" /> | ||||
| {:else if $currentGPSLocation !== undefined } | ||||
|   <!-- If we have a location; this implies that the location access was granted --> | ||||
|   {#if $lastClickWasRecent} | ||||
|     <Location_unlocked class="h-8 w-8" /> | ||||
|   {:else} | ||||
|     <Location class="h-8 w-8" /> | ||||
|   {/if} | ||||
| {:else if $geopermission === "prompt"} | ||||
|   <Location class="h-8 w-8" /> | ||||
| {:else if $geopermission === "requested"} | ||||
|   <!-- Even though disabled, when clicking we request the location again in case the contributor dismissed the location popup --> | ||||
|   <Location | ||||
|     class="h-8 w-8" | ||||
|     style="animation: 3s linear 0s infinite normal none running spin;" | ||||
|   /> | ||||
| {:else if $geopermission === "denied"} | ||||
|   <Location_refused class="h-8 w-8" /> | ||||
| {:else} | ||||
|   <Location | ||||
|     class="h-8 w-8" | ||||
|     style="animation: 3s linear 0s infinite normal none running spin;" | ||||
|   /> | ||||
| {/if} | ||||
|  | @ -1,9 +1,5 @@ | |||
| import { VariableUiElement } from "../Base/VariableUIElement" | ||||
| import Svg from "../../Svg" | ||||
| import { Store, UIEventSource } from "../../Logic/UIEventSource" | ||||
| import GeoLocationHandler from "../../Logic/Actors/GeoLocationHandler" | ||||
| import Hotkeys from "../Base/Hotkeys" | ||||
| import Translations from "../i18n/Translations" | ||||
| import Constants from "../../Models/Constants" | ||||
| import { MapProperties } from "../../Models/MapProperties" | ||||
| 
 | ||||
|  | @ -11,11 +7,12 @@ import { MapProperties } from "../../Models/MapProperties" | |||
|  * Displays an icon depending on the state of the geolocation. | ||||
|  * Will set the 'lock' if clicked twice | ||||
|  */ | ||||
| export class GeolocationControl extends VariableUiElement { | ||||
| export class GeolocationControlState { | ||||
|     public readonly lastClick = new UIEventSource<Date>(undefined) | ||||
|     public readonly lastClickWithinThreeSecs: Store<boolean> | ||||
|     private readonly _geolocationHandler: GeoLocationHandler | ||||
|     private readonly _mapProperties: MapProperties | ||||
|     private readonly _lastClickWithinThreeSecs: Store<boolean> | ||||
| 
 | ||||
|     constructor( | ||||
|         geolocationHandler: GeoLocationHandler, | ||||
|         state: MapProperties, | ||||
|  | @ -41,60 +38,12 @@ export class GeolocationControl extends VariableUiElement { | |||
|                 return timeDiff <= Constants.zoomToLocationTimeout | ||||
|             } | ||||
|         ) | ||||
|         const geolocationState = geolocationHandler?.geolocationState | ||||
|         super( | ||||
|             geolocationState?.permission?.map( | ||||
|                 (permission) => { | ||||
|                     if (permission === "denied") { | ||||
|                         return Svg.location_refused_svg() | ||||
|                     } | ||||
|                     if (!geolocationState.allowMoving.data) { | ||||
|                         return Svg.location_locked_svg() | ||||
|                     } | ||||
| 
 | ||||
|                     if (geolocationState.currentGPSLocation.data === undefined) { | ||||
|                         if (permission === "prompt") { | ||||
|                             return Svg.location_empty_svg() | ||||
|                         } | ||||
|                         // Position not yet found, but permission is either requested or granted: we spin to indicate activity
 | ||||
|                         const icon = | ||||
|                             !geolocationHandler.mapHasMoved.data || lastRequestWithinTimeout.data | ||||
|                                 ? Svg.location_svg() | ||||
|                                 : Svg.location_empty_svg() | ||||
|                         return icon | ||||
|                             .SetClass("cursor-wait") | ||||
|                             .SetStyle("animation: spin 4s linear infinite;") | ||||
|                     } | ||||
| 
 | ||||
|                     // We have a location, so we show a dot in the center
 | ||||
| 
 | ||||
|                     if (lastClickWithinThreeSecs.data) { | ||||
|                         return Svg.location_unlocked_svg() | ||||
|                     } | ||||
| 
 | ||||
|                     // We have a location, so we show a dot in the center
 | ||||
|                     return Svg.location_svg() | ||||
|                 }, | ||||
|                 [ | ||||
|                     geolocationState.currentGPSLocation, | ||||
|                     geolocationState.allowMoving, | ||||
|                     geolocationHandler.mapHasMoved, | ||||
|                     lastClickWithinThreeSecs, | ||||
|                     lastRequestWithinTimeout, | ||||
|                 ] | ||||
|             ) | ||||
|         ) | ||||
| 
 | ||||
|         this._geolocationHandler = geolocationHandler | ||||
|         this._mapProperties = state | ||||
| 
 | ||||
|         this.lastClick = lastClick | ||||
|         this._lastClickWithinThreeSecs = lastClickWithinThreeSecs | ||||
| 
 | ||||
|         this.onClick(() => this.handleClick()) | ||||
|         Hotkeys.RegisterHotkey({ nomod: "L" }, Translations.t.hotkeyDocumentation.geolocate, () => { | ||||
|             this.handleClick() | ||||
|         }) | ||||
|         this.lastClickWithinThreeSecs = lastClickWithinThreeSecs | ||||
| 
 | ||||
|         lastClick.addCallbackAndRunD((_) => { | ||||
|             window.setTimeout(() => { | ||||
|  | @ -148,7 +97,7 @@ export class GeolocationControl extends VariableUiElement { | |||
|             state.zoom.update((z) => z + 3) | ||||
|         } | ||||
| 
 | ||||
|         if (this._lastClickWithinThreeSecs.data) { | ||||
|         if (this.lastClickWithinThreeSecs.data) { | ||||
|             geolocationState.allowMoving.setData(false) | ||||
|             lastClick.setData(undefined) | ||||
|             return | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ | |||
|   import MapControlButton from "./Base/MapControlButton.svelte" | ||||
|   import ToSvelte from "./Base/ToSvelte.svelte" | ||||
|   import If from "./Base/If.svelte" | ||||
|   import { GeolocationControl } from "./BigComponents/GeolocationControl" | ||||
|   import type { Feature } from "geojson" | ||||
|   import SelectedElementView from "./BigComponents/SelectedElementView.svelte" | ||||
|   import LayerConfig from "../Models/ThemeConfig/LayerConfig" | ||||
|  | @ -65,6 +64,8 @@ | |||
|   import ImageOperations from "./Image/ImageOperations.svelte" | ||||
|   import VisualFeedbackPanel from "./BigComponents/VisualFeedbackPanel.svelte" | ||||
|   import { Orientation } from "../Logic/Web/Orientation" | ||||
|   import GeolocationControl from "./BigComponents/GeolocationControl.svelte" | ||||
|   import Compass_arrow from "../assets/svg/Compass_arrow.svelte" | ||||
| 
 | ||||
|   export let state: ThemeViewState | ||||
|   let layout = state.layout | ||||
|  | @ -111,8 +112,6 @@ | |||
|   ) | ||||
|   let previewedImage = state.previewedImage | ||||
| 
 | ||||
|   let geolocationControl = new GeolocationControl(state.geolocation, mapproperties, state.lastGeolocationRequestMoment) | ||||
| 
 | ||||
|   function forwardEventToMap(e: KeyboardEvent) { | ||||
|     const mlmap = state.map.data | ||||
|     if (!mlmap) { | ||||
|  | @ -262,27 +261,20 @@ | |||
|         <Min class="h-8 w-8" /> | ||||
|       </MapControlButton> | ||||
|       <If condition={featureSwitches.featureSwitchGeolocation}> | ||||
|         <div class="relative m-0.5 h-12 w-12 p-0 sm:p-1 md:m-1"> | ||||
|         <div class="relative m-0.5 md:m-1"> | ||||
|           <MapControlButton arialabel={Translations.t.general.labels.jumpToLocation} | ||||
|                             on:click={() => state.geolocationControl.handleClick()} | ||||
|                             on:keydown={forwardEventToMap} | ||||
|           > | ||||
|             <GeolocationControl {state} /> <!-- h-8 w-8 + p-0.5 sm:p-1 + 2px border => 9 sm: 10 in total--> | ||||
|           </MapControlButton> | ||||
|           {#if $compassLoaded} | ||||
|             <div class="absolute top-1/2 left-1/2 w-0 h-0"> | ||||
|               <div class="w-5 h-5" | ||||
|                    style={`rotate: calc(${-$compass}deg + 225deg); transform-origin: 0% 0%; background: var(--button-background);`} /> | ||||
|             <div class="absolute top-0 left-0 w-0 h-0 m-0.5 sm:m-1"> | ||||
|               <Compass_arrow class="compass_arrow" style={`rotate: calc(${-$compass}deg + 225deg); transform-origin: 50% 50%;`} /> | ||||
|             </div> | ||||
|           {/if} | ||||
|           <div class="absolute top-0 left-0 p-0.5 md:p-1"> | ||||
| 
 | ||||
|             <MapControlButton arialabel={Translations.t.general.labels.jumpToLocation} | ||||
|                               cls="m-0 p-0.5 sm:p-1" | ||||
|                               on:click={() => geolocationControl.handleClick()} | ||||
|                               on:keydown={forwardEventToMap} | ||||
|             > | ||||
|               <ToSvelte | ||||
|                 construct={geolocationControl.SetClass("block w-8 h-8")} | ||||
|               /> | ||||
|             </MapControlButton> | ||||
|           </div> | ||||
| 
 | ||||
|         </div> | ||||
| 
 | ||||
|       </If> | ||||
| 
 | ||||
|     </div> | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| <script> | ||||
| export let color = "#000000" | ||||
| </script> | ||||
|  <svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1">     <g id="surface1">         <path                 style="fill:{color};"                 class="selectable"               d="M 375 187.5 C 375 291.054688 291.054688 375 187.5 375 C 83.945312 375 0 291.054688 0 187.5 C 0 83.945312 83.945312 0 187.5 0 C 291.054688 0 375 83.945312 375 187.5 Z M 375 187.5 "/>     </g> </svg>  | ||||
|  <svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown    width="375px"    height="375px"    viewBox="0 0 375 375"    version="1.1"    id="svg1"    sodipodi:docname="circle.svg"    inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"    xmlns="http://www.w3.org/2000/svg"    xmlns:svg="http://www.w3.org/2000/svg">   <defs      id="defs1" />   <sodipodi:namedview      id="namedview1"      pagecolor="#505050"      bordercolor="#eeeeee"      borderopacity="1"      inkscape:showpageshadow="0"      inkscape:pageopacity="0"      inkscape:pagecheckerboard="0"      inkscape:deskcolor="#d1d1d1"      inkscape:zoom="2.056"      inkscape:cx="187.5"      inkscape:cy="187.5"      inkscape:window-width="1920"      inkscape:window-height="995"      inkscape:window-x="0"      inkscape:window-y="0"      inkscape:window-maximized="1"      inkscape:current-layer="svg1" />   <path      style="fill:{color}"      class="selectable"      d="M 375,187.5 C 375,291.05469 291.05469,375 187.5,375 83.945312,375 0,291.05469 0,187.5 0,83.945312 83.945312,0 187.5,0 291.05469,0 375,83.945312 375,187.5 Z m 0,0"      id="path1" /> </svg>  | ||||
							
								
								
									
										4
									
								
								src/assets/svg/Compass_arrow.svelte
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/assets/svg/Compass_arrow.svelte
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| <script> | ||||
| export let color = "#000000" | ||||
| </script> | ||||
|  <svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown    width="375px"    height="375px"    viewBox="0 0 375 375"    version="1.1"    id="svg1"    sodipodi:docname="compass_arrow.svg"    inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"    xmlns="http://www.w3.org/2000/svg"    xmlns:svg="http://www.w3.org/2000/svg">   <defs      id="defs1" />   <sodipodi:namedview      id="namedview1"      pagecolor="#505050"      bordercolor="#eeeeee"      borderopacity="1"      inkscape:showpageshadow="0"      inkscape:pageopacity="0"      inkscape:pagecheckerboard="0"      inkscape:deskcolor="#d1d1d1"      inkscape:zoom="1.0410569"      inkscape:cx="33.139398"      inkscape:cy="182.98711"      inkscape:window-width="1920"      inkscape:window-height="995"      inkscape:window-x="0"      inkscape:window-y="0"      inkscape:window-maximized="1"      inkscape:current-layer="svg1" />   <path      id="rect2"      style="fill:{color};stroke:none;stroke-linecap:round;fill-opacity:1;stroke-opacity:1"      d="M 16.835505,17.477497 79.869453,33.962116 V 80.511444 H 33.96212 Z"      sodipodi:nodetypes="ccccc" /> </svg>  | ||||
|  | @ -590,6 +590,21 @@ a.link-underline { | |||
|     overflow: visible !important; | ||||
| } | ||||
| 
 | ||||
| .compass_arrow { | ||||
|     width: calc( 2.5rem - 1px ) ;  | ||||
|     height: calc( 2.5rem - 1px ) | ||||
| } | ||||
| 
 | ||||
| @media (min-width: 640px) { | ||||
|     .compass_arrow { | ||||
|         width: calc( 2.75rem - 1px ) ; | ||||
|         height: calc( 2.75rem - 1px ) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @-webkit-keyframes glowing-drop-shadow { | ||||
|     from { | ||||
|         filter: drop-shadow(5px 5px 60px rgb(128 128 128 / 0.6)); | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <!-- We disable 'user-scalable'. As we are working with a map, the user might zoom in using a popup, close the popup and _not_ be able to zoom out again. --> | ||||
|     <meta content="width=device-width, initial-scale=1.0, user-scalable=no" name="viewport"> | ||||
|     <meta content="width=device-width, initial-scale=1.0, user-scalable=yes" name="viewport"> | ||||
|     <!-- CSP --> | ||||
|     <link href="./css/mobile.css" rel="stylesheet"/> | ||||
|     <link href="./css/openinghourstable.css" rel="stylesheet"/> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue