Skip to content

Commit

Permalink
Merge pull request #864 from geoadmin/bug-PB-521-goelocation
Browse files Browse the repository at this point in the history
PB-521: fix geolocation tracking, zindex and accuracy and several geolocation improvements
  • Loading branch information
pakb authored May 27, 2024
2 parents 51a0609 + b36092a commit ac76f67
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 92 deletions.
11 changes: 0 additions & 11 deletions src/modules/map/components/common/mouse-click.composable.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { computed } from 'vue'
import { useStore } from 'vuex'

import { ClickInfo, ClickType } from '@/store/modules/map.store'
Expand All @@ -14,9 +13,6 @@ export function useMouseOnMap() {
let contextMenuTimeout = null

const store = useStore()
const isCurrentlyTrackingGeoLocation = computed(
() => store.state.geolocation.active && store.state.geolocation.tracking
)

/**
* @param {[Number, Number]} screenPosition
Expand Down Expand Up @@ -73,13 +69,6 @@ export function useMouseOnMap() {
if (isPointerDown) {
isStillOnStartingPosition = false
}
if (isCurrentlyTrackingGeoLocation.value) {
// stop tracking the user geolocation to the center of the view as soon as the map is dragged
store.dispatch('setGeolocationTracking', {
tracking: false,
...dispatcher,
})
}
}

function onRightClick(screenPosition, coordinate) {
Expand Down
56 changes: 8 additions & 48 deletions src/modules/map/components/common/z-index.composable.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ export function useLayerZIndexCalculation() {
}
return [store.state.layers.currentBackgroundLayer]
})
const selectedFeatures = computed(() => store.getters.selectedFeatures)
const pinnedLocation = computed(() => store.state.map.pinnedLocation)
const previewLocation = computed(() => store.state.map.previewedPinnedLocation)
const crossHair = computed(() => store.state.position.crossHair)
const showTileDebugInfo = computed(() => store.state.debug.showTileDebugInfo)
const showLayerExtents = computed(() => store.state.debug.showLayerExtents)

const visibleLayers = computed(() => {
const visibleLayersWithZIndex = [...backgroundLayers.value]
Expand Down Expand Up @@ -51,48 +45,13 @@ export function useLayerZIndexCalculation() {
return visibleLayers.value.length + nbOfSubLayers
})
const zIndexHighlightedFeatures = computed(() => startingZIndexForThingsOnTopOfLayers.value)
const zIndexDroppedPin = computed(() => {
let zIndex = zIndexHighlightedFeatures.value
if (selectedFeatures.value.length > 0) {
zIndex++
}
return zIndex
})
const zIndexPreviewPosition = computed(() => {
let zIndex = zIndexDroppedPin.value
if (pinnedLocation.value) {
zIndex++
}
return zIndex
})
const zIndexCrossHair = computed(() => {
let zIndex = zIndexPreviewPosition.value
if (previewLocation.value) {
zIndex++
}
return zIndex
})
const zIndexTileInfo = computed(() => {
let zIndex = zIndexCrossHair.value
if (crossHair.value) {
zIndex++
}
return zIndex
})
const zIndexLayerExtents = computed(() => {
let zIndex = zIndexTileInfo.value
if (showTileDebugInfo.value) {
zIndex++
}
return zIndex
})
const nextAvailableZIndex = computed(() => {
let zIndex = zIndexLayerExtents.value
if (showLayerExtents.value) {
zIndex++
}
return zIndex
})
const zIndexDroppedPin = computed(() => zIndexHighlightedFeatures.value + 1)
const zIndexPreviewPosition = computed(() => zIndexDroppedPin.value + 1)
const zIndexCrossHair = computed(() => zIndexPreviewPosition.value + 1)
const zIndexGeolocation = computed(() => zIndexCrossHair.value + 1)
const zIndexTileInfo = computed(() => zIndexGeolocation.value + 1)
const zIndexLayerExtents = computed(() => zIndexTileInfo.value + 1)
const nextAvailableZIndex = computed(() => zIndexLayerExtents.value + 1)

/**
* Gives the z-index of a layer, taking into account if the map is shown in 3D or not. This
Expand Down Expand Up @@ -129,6 +88,7 @@ export function useLayerZIndexCalculation() {
zIndexDroppedPin,
zIndexPreviewPosition,
zIndexCrossHair,
zIndexGeolocation,
zIndexTileInfo,
zIndexLayerExtents,
nextAvailableZIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,7 @@ useAddLayerToMap(layer, olMap, zIndex)
watch(position, (newPosition) => accuracyCircle.setCenter(newPosition))
watch(accuracy, (newAccuracy) => accuracyCircle.setRadius(newAccuracy))
</script>

<template>
<slot />
</template>
7 changes: 5 additions & 2 deletions src/store/modules/geolocation.store.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import log from '@/utils/logging'
import { isNumber } from '@/utils/numberUtils'

const state = {
/**
Expand All @@ -20,7 +21,7 @@ const state = {
*/
tracking: false,
/**
* Device position in EPSG:3857 (meters) [x, y]
* Device position in the current application projection [x, y]
*
* @type Array<Number>
*/
Expand Down Expand Up @@ -62,8 +63,10 @@ const actions = {
}
},
setGeolocationAccuracy: ({ commit }, { accuracy, dispatcher }) => {
if (Number.isInteger(accuracy)) {
if (isNumber(accuracy)) {
commit('setGeolocationAccuracy', { accuracy: Number(accuracy), dispatcher })
} else {
log.error(`Invalid geolocation accuracy: ${accuracy}`)
}
},
}
Expand Down
97 changes: 66 additions & 31 deletions src/store/plugins/geolocation-management.plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const readPosition = (position, projection) => {
}

const handlePositionAndDispatchToStore = (position, store) => {
log.debug(`Received position from geolocation`, position, store.state.geolocation)
const positionProjected = readPosition(position, store.state.position.projection)
store.dispatch('setGeolocationPosition', {
position: positionProjected,
Expand Down Expand Up @@ -65,6 +66,60 @@ const handlePositionError = (error, store) => {
}
}

const activeGeolocation = (store, state) => {
if (store.state.geolocation.position[0] !== 0 && store.state.geolocation.position[1] !== 0) {
// if we have a previous position use it first to be more reactive but set a
// bad accuracy as we don't know how exact it is.
store.dispatch('setCenter', {
center: store.state.geolocation.position,
...dispatcher,
})
store.dispatch('setGeolocationAccuracy', {
accuracy: 50 * 1000, // 50 km
...dispatcher,
})
}
navigator.geolocation.getCurrentPosition(
(position) => {
log.debug(
`Geolocation API current position`,
position,
`firstTimeActivatingGeolocation=${firstTimeActivatingGeolocation}`
)
// if geoloc was previously denied, we clear the flag
if (state.geolocation.denied) {
store.dispatch('setGeolocationDenied', {
denied: false,
...dispatcher,
})
}
// register a watcher
geolocationWatcher = navigator.geolocation.watchPosition(
(position) => handlePositionAndDispatchToStore(position, store),
(error) => handlePositionError(error, store)
)

// handle current position
handlePositionAndDispatchToStore(position, store)

// set zoom level
let zoomLevel = STANDARD_ZOOM_LEVEL_1_25000_MAP
if (state.position.projection instanceof CustomCoordinateSystem) {
zoomLevel = state.position.projection.transformStandardZoomLevelToCustom(zoomLevel)
}
store.dispatch('setZoom', {
zoom: zoomLevel,
...dispatcher,
})
},
(error) => handlePositionError(error, store),
{
maximumAge: 5 * 60 * 1000, // 5 minutes
timeout: 2 * 60 * 1000, // 2 minutes
}
)
}

/**
* Plugin that handle the HTML5 Geolocation API interaction, and dispatch its output to the store
* when geolocation is active.
Expand All @@ -76,41 +131,21 @@ const geolocationManagementPlugin = (store) => {
// listening to the start/stop of geolocation
if (mutation.type === 'setGeolocationActive') {
if (state.geolocation.active) {
navigator.geolocation.getCurrentPosition(
(position) => {
// if geoloc was previously denied, we clear the flag
if (state.geolocation.denied) {
store.dispatch('setGeolocationDenied', {
denied: false,
...dispatcher,
})
}
handlePositionAndDispatchToStore(position, store)
if (firstTimeActivatingGeolocation) {
firstTimeActivatingGeolocation = false
let zoomLevel = STANDARD_ZOOM_LEVEL_1_25000_MAP
if (state.position.projection instanceof CustomCoordinateSystem) {
zoomLevel =
state.position.projection.transformStandardZoomLevelToCustom(
zoomLevel
)
}
store.dispatch('setZoom', {
zoom: zoomLevel,
...dispatcher,
})
}
geolocationWatcher = navigator.geolocation.watchPosition(
(position) => handlePositionAndDispatchToStore(position, store),
(error) => handlePositionError(error, store)
)
},
(error) => handlePositionError(error, store)
)
activeGeolocation(store, state)
} else if (geolocationWatcher) {
log.debug(`Geolocation clear watcher`)
navigator.geolocation.clearWatch(geolocationWatcher)
geolocationWatcher = null
}
} else if (
mutation.type === 'setCenter' &&
mutation.payload?.dispatcher !== dispatcher.dispatcher
) {
// if we moved the map we disabled the tracking (unless the tracking moved the map)
store.dispatch('setGeolocationTracking', {
tracking: false,
...dispatcher,
})
}
})
}
Expand Down

0 comments on commit ac76f67

Please sign in to comment.