Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PB-494: Add address bar on 3D map #880

Merged
merged 10 commits into from
Jun 13, 2024
5 changes: 5 additions & 0 deletions src/modules/map/components/cesium/CesiumMap.vue
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ export default {
'setFeatureInfoPosition',
'setCenter',
'mapModuleReady',
'setViewerReady',
]),
toggleTooltip() {
this.toggleFloatingTooltip(dispatcher)
Expand Down Expand Up @@ -429,6 +430,10 @@ export default {
globe.maximumScreenSpaceError = 30
}
this.mapModuleReady(dispatcher)
this.setViewerReady({
isViewerReady: true,
...dispatcher,
})
},
highlightSelectedFeatures() {
const [firstFeature] = this.selectedFeatures
Expand Down
122 changes: 122 additions & 0 deletions src/modules/map/components/cesium/CesiumMouseTracker.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<script setup>
import { Cartographic, Math, ScreenSpaceEventHandler, ScreenSpaceEventType } from 'cesium'
import proj4 from 'proj4'
import { computed, inject, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useStore } from 'vuex'

import allFormats, { LV03Format, LV95Format } from '@/utils/coordinates/coordinateFormat'
import log from '@/utils/logging'

const mousePosition = ref(null)
const displayedFormatId = ref(LV95Format.id)

const store = useStore()
const i18n = useI18n()

const is3DReady = computed(() => store.state.cesium.isViewerReady)
const projection = computed(() => store.state.position.projection)

const dispatcher = { dispatcher: 'CesiumMouseTracker.vue' }
const getViewer = inject('getViewer', () => {}, true)

let handler = null

watch(
is3DReady,
(newValue) => {
if (newValue) {
setupHandler()
}
},
{ immediate: true }
)

onMounted(() => {
nextTick(() => {
setupHandler()
})
})

onBeforeUnmount(() => {
if (handler) {
handler.removeInputAction(ScreenSpaceEventType.MOUSE_MOVE)
handler.destroy()
}
})

function setupHandler() {
if (!getViewer()) {
return
}
handler = new ScreenSpaceEventHandler(getViewer().scene.canvas)
ismailsunni marked this conversation as resolved.
Show resolved Hide resolved
const viewer = getViewer()
handler.setInputAction((movement) => {
const ray = viewer.camera.getPickRay(movement.endPosition)
const cartesian = viewer.scene.globe.pick(ray, viewer.scene)
if (cartesian) {
const cartographic = Cartographic.fromCartesian(cartesian)
const longitude = Math.toDegrees(cartographic.longitude)
const latitude = Math.toDegrees(cartographic.latitude)
let coordinate = proj4('EPSG:4326', projection.value.getCode(), [longitude, latitude])
coordinate.push(cartographic.height)

mousePosition.value.textContent = formatCoordinate(coordinate)
}
}, ScreenSpaceEventType.MOUSE_MOVE)
}

function showCoordinateLabel(displayedFormat) {
return displayedFormat?.id === LV95Format.id || displayedFormat?.id === LV03Format.id
}

function setDisplayedFormatWithId() {
store.dispatch('setDisplayedFormatId', {
displayedFormatId: displayedFormatId.value,
...dispatcher,
})
}

function formatCoordinate(coordinate) {
const displayedFormat = allFormats.find((format) => format.id === displayedFormatId.value)
if (displayedFormat) {
if (showCoordinateLabel(displayedFormat)) {
return `${i18n.t('coordinates_label')} ${displayedFormat.format(
coordinate,
projection.value
)}`
}
return displayedFormat.format(coordinate, projection.value, true)
} else {
log.error('Unknown coordinates display format', displayedFormatId.value)
}
}
ismailsunni marked this conversation as resolved.
Show resolved Hide resolved
</script>

<template>
<select
v-model="displayedFormatId"
class="map-projection form-control-xs"
data-cy="mouse-position-select"
@change="setDisplayedFormatWithId"
>
<option v-for="format in allFormats" :key="format.id" :value="format.id">
{{ format.label }}
</option>
</select>
<div ref="mousePosition" class="mouse-position" data-cy="mouse-position"></div>
</template>

<style lang="scss" scoped>
.mouse-position {
display: none;
min-width: 10em;
text-align: left;
white-space: nowrap;
}
@media (any-hover: hover) {
.mouse-position {
display: block;
}
}
</style>
10 changes: 10 additions & 0 deletions src/store/modules/cesium.store.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ export default {
* @type Boolean
*/
showLabels: true,
/**
* Flag telling if the 3D viewer is ready or not
*
* @type Boolean
*/
isViewerReady: false,
},
getters: {
backgroundLayersFor3D(state, _, rootState) {
Expand Down Expand Up @@ -118,6 +124,9 @@ export default {
setShowLabels({ commit }, { showLabels, dispatcher }) {
commit('setShowLabels', { showLabels, dispatcher })
},
setViewerReady({ commit }, { isViewerReady, dispatcher }) {
commit('setViewerReady', { isViewerReady, dispatcher })
},
},
mutations: {
set3dActive: (state, { active }) => (state.active = active),
Expand All @@ -130,5 +139,6 @@ export default {
state.showConstructions = showConstructionsBuildings
},
setShowLabels: (state, { showLabels }) => (state.showLabels = showLabels),
setViewerReady: (state, { isViewerReady }) => (state.isViewerReady = isViewerReady),
},
}
9 changes: 9 additions & 0 deletions src/utils/coordinates/CoordinateSystem.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,13 @@ export default class CoordinateSystem {
}
return matrixIds
}

/**
* Returns the EPSG identifier of this coordinate system
*
* @returns {String}
*/
getCode() {
return `EPSG:${this.epsgNumber}`
}
}
12 changes: 9 additions & 3 deletions src/views/MapView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useStore } from 'vuex'

import I18nModule from '@/modules/i18n/I18nModule.vue'
import InfoboxModule from '@/modules/infobox/InfoboxModule.vue'
import CesiumMouseTracker from '@/modules/map/components/cesium/CesiumMouseTracker.vue'
import BackgroundSelector from '@/modules/map/components/footer/backgroundSelector/BackgroundSelector.vue'
import MapFooter from '@/modules/map/components/footer/MapFooter.vue'
import MapFooterAppCopyright from '@/modules/map/components/footer/MapFooterAppCopyright.vue'
Expand Down Expand Up @@ -77,9 +78,14 @@ onMounted(() => {
<template #middle>
<InfoboxModule />
</template>
<template v-if="!is3DActive && !isPhoneMode" #bottom-left>
<OpenLayersScale />
<OpenLayersMouseTracker />
<template #bottom-left>
<template v-if="!is3DActive && !isPhoneMode">
<OpenLayersScale />
<OpenLayersMouseTracker />
</template>
<template v-if="is3DActive && !isPhoneMode">
<CesiumMouseTracker />
</template>
</template>
<template v-if="!isPhoneMode" #bottom-right>
<MapFooterAppVersion />
Expand Down
Loading