forked from MapComplete/MapComplete
Add QR-code to all popups, add direction indicator to popup and visual feedback, make reviews accessible to screenreaders (both to read them and to make them)
This commit is contained in:
parent
5567869bb4
commit
bfd818cb38
33 changed files with 415 additions and 98 deletions
|
@ -4,12 +4,16 @@
|
|||
import ThemeViewState from "../../Models/ThemeViewState"
|
||||
import Tr from "../Base/Tr.svelte"
|
||||
import Translations from "../i18n/Translations"
|
||||
import { Orientation } from "../../Sensors/Orientation"
|
||||
import { Translation } from "../i18n/Translation"
|
||||
import Constants from "../../Models/Constants"
|
||||
|
||||
/**
|
||||
* Indicates how far away the viewport center is from the current user location
|
||||
*/
|
||||
export let state: ThemeViewState
|
||||
const t = Translations.t.general.visualFeedback
|
||||
const relativeDir = t.directionsRelative
|
||||
let map = state.mapProperties
|
||||
|
||||
let currentLocation = state.geolocation.geolocationState.currentGPSLocation
|
||||
|
@ -23,14 +27,29 @@
|
|||
const distanceInMeters = Math.round(GeoOperations.distanceBetween(gps, mapCenter))
|
||||
const distance = GeoOperations.distanceToHuman(distanceInMeters)
|
||||
const bearing = Math.round(GeoOperations.bearing(gps, mapCenter))
|
||||
return { distance, bearing, distanceInMeters }
|
||||
const bearingDirection = GeoOperations.bearingToHuman(bearing)
|
||||
return { distance, bearing, distanceInMeters, bearingDirection }
|
||||
}, [currentLocation])
|
||||
let hasCompass = Orientation.singleton.gotMeasurement
|
||||
let compass = Orientation.singleton.alpha
|
||||
let relativeBearing: Store<{distance: string, bearing: Translation}> =
|
||||
compass.mapD(compass => {
|
||||
const bearing: Translation = relativeDir[GeoOperations.bearingToHumanRelative(distanceToCurrentLocation.data.bearing - compass)]
|
||||
return {bearing, distance: distanceToCurrentLocation.data.distance}
|
||||
}, [distanceToCurrentLocation])
|
||||
let viewportCenterDetails = Translations.DynamicSubstitute(t.viewportCenterDetails, relativeBearing)
|
||||
let viewportCenterDetailsAbsolute = Translations.DynamicSubstitute(t.viewportCenterDetails, distanceToCurrentLocation.map(({distance, bearing}) => {
|
||||
return {distance, bearing: t.directionsAbsolute[GeoOperations.bearingToHuman(bearing)]}
|
||||
}))
|
||||
|
||||
</script>
|
||||
|
||||
{#if $currentLocation !== undefined}
|
||||
{#if $distanceToCurrentLocation.distanceInMeters < 20}
|
||||
{#if $distanceToCurrentLocation.distanceInMeters < Constants.viewportCenterCloseToGpsCutoff}
|
||||
<Tr t={t.viewportCenterCloseToGps} />
|
||||
{:else if $hasCompass}
|
||||
{$viewportCenterDetails}
|
||||
{:else}
|
||||
<Tr t={t.viewportCenterDetails.Subs($distanceToCurrentLocation)} />
|
||||
{$viewportCenterDetailsAbsolute}
|
||||
{/if}
|
||||
{/if}
|
||||
|
|
|
@ -55,11 +55,10 @@
|
|||
|
||||
{#if currentLocation}
|
||||
<div
|
||||
role="alert"
|
||||
aria-live="assertive"
|
||||
class="normal-background border-interactive rounded-full px-2 flex flex-col items-center"
|
||||
>
|
||||
{currentLocation}
|
||||
{currentLocation}.
|
||||
<MapCenterDetails {state}/>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||
import TagRenderingAnswer from "../Popup/TagRendering/TagRenderingAnswer.svelte"
|
||||
import DirectionIndicator from "../Base/DirectionIndicator.svelte"
|
||||
import ThemeViewState from "../../Models/ThemeViewState"
|
||||
|
||||
export let state: SpecialVisualizationState
|
||||
export let feature: Feature
|
||||
|
@ -14,11 +15,14 @@
|
|||
|
||||
</script>
|
||||
|
||||
<a class="small flex space-x-1 cursor-pointer w-fit" href={`#${feature.properties.id}`}>
|
||||
<span class="inline-flex gap-x-1">
|
||||
|
||||
<a class="small flex space-x-0.5 cursor-pointer w-fit items-center" href={`#${feature.properties.id}`}>
|
||||
{#if i !== undefined}
|
||||
<span class="font-bold">{i + 1} </span>
|
||||
{/if}
|
||||
<TagRenderingAnswer config={layer.title} extraClasses="inline-flex w-fit" {layer} selectedElement={feature} {state}
|
||||
{tags} />
|
||||
<DirectionIndicator {feature} {state} />
|
||||
</a>
|
||||
<DirectionIndicator {feature} {state} />
|
||||
</span>
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
lastAction.stabilized(750).addCallbackAndRunD((_) => lastAction.setData(undefined))
|
||||
</script>
|
||||
|
||||
<div aria-live="assertive" class="p-1 interactive" role="alert">
|
||||
<div aria-live="assertive" class="p-1 bg-white m-1 rounded">
|
||||
{#if $lastAction?.key === "out"}
|
||||
<Tr t={t.out.Subs({z: map.zoom.data - 1})} />
|
||||
{:else if $lastAction?.key === "in"}
|
||||
|
@ -46,13 +46,11 @@
|
|||
<div class="pointer-events-auto">
|
||||
<Tr t={$translationWithLength} />
|
||||
<MapCenterDetails {state} />
|
||||
<ol>
|
||||
<div class="grid grid-cols-3 space-x-1 space-y-0.5">
|
||||
{#each $centerFeatures.slice(0, 9) as feat, i (feat.properties.id)}
|
||||
<li>
|
||||
<Summary {state} feature={feat} {i} />
|
||||
</li>
|
||||
<Summary {state} feature={feat} {i} />
|
||||
{/each}
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue