Skip to content

BGDIINF_SB-3214 : add dedicated zoom in/out 3D buttons #582

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

Merged
merged 1 commit into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 14 additions & 15 deletions src/modules/map/components/cesium/CesiumMap.vue
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,14 @@
<FeatureEdit v-if="editFeature" :read-only="true" :feature="editFeature" />
<FeatureList direction="column" />
</CesiumPopover>
<cesium-compass v-show="isDesktopMode && !isFullScreenMode" ref="compass" class="compass" />
<CesiumToolbox
v-if="viewerCreated && isDesktopMode && !isFullScreenMode"
class="cesium-toolbox position-absolute start-50 translate-middle-x"
/>
<slot />
</div>
</template>
<script>
import '@geoblocks/cesium-compass'
import 'cesium/Build/Cesium/Widgets/widgets.css'

import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
Expand Down Expand Up @@ -111,6 +113,7 @@ import FeatureEdit from '@/modules/infobox/components/FeatureEdit.vue'
import FeatureList from '@/modules/infobox/components/FeatureList.vue'
import CesiumInternalLayer from '@/modules/map/components/cesium/CesiumInternalLayer.vue'
import CesiumPopover from '@/modules/map/components/cesium/CesiumPopover.vue'
import CesiumToolbox from '@/modules/map/components/cesium/CesiumToolbox.vue'
import {
CAMERA_MAX_PITCH,
CAMERA_MAX_ZOOM_DISTANCE,
Expand All @@ -135,7 +138,14 @@ import { identifyGeoJSONFeatureAt } from '@/utils/identifyOnVectorLayer'
import log from '@/utils/logging'

export default {
components: { FontAwesomeIcon, CesiumPopover, FeatureEdit, FeatureList, CesiumInternalLayer },
components: {
CesiumToolbox,
FontAwesomeIcon,
CesiumPopover,
FeatureEdit,
FeatureList,
CesiumInternalLayer,
},
provide() {
return {
// sharing cesium viewer object with children components
Expand Down Expand Up @@ -327,10 +337,6 @@ export default {
requestRenderMode: true,
})

const compass = this.$refs.compass
compass.scene = this.viewer.scene
compass.clock = this.viewer.clock

const scene = this.viewer.scene
scene.useDepthPicking = true
scene.pickTranslucentDepth = true
Expand Down Expand Up @@ -564,15 +570,8 @@ export default {
display: none !important;
}

$compass-size: 95px;
cesium-compass {
position: absolute;
.cesium-toolbox {
bottom: $footer-height + $screen-padding-for-ui-elements;
right: 50%;
z-index: $zindex-map + 1;
width: $compass-size;
height: $compass-size;
--cesium-compass-stroke-color: rgba(0, 0, 0, 0.6);
--cesium-compass-fill-color: rgb(224, 225, 226);
}
</style>
96 changes: 96 additions & 0 deletions src/modules/map/components/cesium/CesiumToolbox.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<script setup>
import '@geoblocks/cesium-compass'

import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { Ray } from 'cesium'
import { computed, inject, onMounted, ref } from 'vue'
import { useStore } from 'vuex'

import log from '@/utils/logging'

const compass = ref(null)

const store = useStore()

const isDesktopMode = computed(() => store.getters.isDesktopMode)
const resolution = computed(() => store.getters.resolution)

const getViewer = inject('getViewer')

const viewer = getViewer()

onMounted(() => {
if (viewer) {
compass.value.scene = viewer.scene
compass.value.clock = viewer.clock
} else {
log.error('No Cesium viewer found, could not link compass')
}
})

const resolutionRatioForZoomInOut = 200
const step = computed(() => resolution.value * resolutionRatioForZoomInOut)

function moveCamera(distance) {
const camera = viewer.scene.camera
if (camera) {
camera.flyTo({
destination: Ray.getPoint(new Ray(camera.position, camera.direction), distance),
orientation: {
heading: camera.heading,
pitch: camera.pitch,
roll: camera.roll,
},
duration: 0.25,
})
}
}

function moveForward() {
moveCamera(step.value)
}

function moveBackward() {
moveCamera(-step.value)
}
</script>

<template>
<div class="cesium-toolbox">
<button class="cesium-toolbox-button" @click="moveForward">
<FontAwesomeIcon icon="plus" />
</button>
<cesium-compass v-show="isDesktopMode" ref="compass" class="cesium-toolbox-compass" />
<button class="cesium-toolbox-button" @click="moveBackward">
<FontAwesomeIcon icon="minus" />
</button>
</div>
</template>

<style lang="scss" scoped>
@import 'src/scss/webmapviewer-bootstrap-theme';

.cesium-toolbox {
display: flex;

$compass-size: 95px;
$button-size: $compass-size / 2;
&-button {
width: $button-size;
height: $button-size;
border-radius: $button-size / 2;
border: 2px solid rgba(0, 0, 0, 0.4);
background: rgb(224, 225, 226);
font-size: $button-size / 2.5;
color: rgba(0, 0, 0, 0.8);
}

&-compass {
position: relative;
width: $compass-size;
height: $compass-size;
--cesium-compass-stroke-color: rgba(0, 0, 0, 0.6);
--cesium-compass-fill-color: rgb(224, 225, 226);
}
}
</style>
135 changes: 64 additions & 71 deletions src/modules/menu/MenuModule.vue
Original file line number Diff line number Diff line change
@@ -1,3 +1,63 @@
<script setup>
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { computed, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useStore } from 'vuex'

import BlackBackdrop from '@/modules/menu/components/BlackBackdrop.vue'
import DebugToolbar from '@/modules/menu/components/debug/DebugToolbar.vue'
import HeaderWithSearch from '@/modules/menu/components/header/HeaderWithSearch.vue'
import MenuTray from '@/modules/menu/components/menu/MenuTray.vue'
import TimeSlider from '@/modules/menu/components/timeslider/TimeSlider.vue'
import FullScreenButton from '@/modules/menu/components/toolboxRight/FullScreenButton.vue'
import GeolocButton from '@/modules/menu/components/toolboxRight/GeolocButton.vue'
import TimeSliderButton from '@/modules/menu/components/toolboxRight/TimeSliderButton.vue'
import Toggle3dButton from '@/modules/menu/components/toolboxRight/Toggle3dButton.vue'
import ZoomButtons from '@/modules/menu/components/toolboxRight/ZoomButtons.vue'

const showTimeSlider = ref(false)

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

const isGeolocationActive = computed(() => store.state.geolocation.active)
const isGeolocationDenied = computed(() => store.state.geolocation.denied)
const showMenu = computed(() => store.state.ui.showMenu)
const isFullscreenMode = computed(() => store.state.ui.fullscreenMode)
const isEmbedded = computed(() => store.state.ui.embeddedMode)
const previewYear = computed(() => store.state.layers.previewYear)
const inDrawingMode = computed(() => store.state.ui.showDrawingOverlay)
const is3dActive = computed(() => store.state.cesium.active)

const isHeaderShown = computed(() => store.getters.isHeaderShown)
const isPhoneMode = computed(() => store.getters.isPhoneMode)
const isDesktopMode = computed(() => store.getters.isDesktopMode)
const isMenuShown = computed(() => store.getters.isMenuShown)
const isMenuTrayShown = computed(() => store.getters.isMenuTrayShown)
const hasDevSiteWarning = computed(() => store.getters.hasDevSiteWarning)
const visibleLayersWithTimeConfig = computed(() => store.getters.visibleLayersWithTimeConfig)

watch(previewYear, () => {
// hiding the time slider if the preview has been cleared
if (!previewYear.value) {
showTimeSlider.value = false
}
})

function toggleGeolocation() {
store.dispatch('toggleGeolocation')
}
function increaseZoom() {
store.dispatch('increaseZoom')
}
function decreaseZoom() {
store.dispatch('decreaseZoom')
}
function toggleMenu() {
store.dispatch('toggleMenu')
}
</script>

<template>
<div class="menu position-absolute w-100 h-100 start-0 top-0 pe-none">
<!-- In order to place the drawing toolbox correctly (so that zoom/geolocation button are under, etc...)
Expand Down Expand Up @@ -33,7 +93,7 @@
@click="toggleGeolocation"
/>
<ZoomButtons
v-if="!isFullscreenMode"
v-if="!isFullscreenMode && !is3dActive"
@zoom-in="increaseZoom"
@zoom-out="decreaseZoom"
/>
Expand Down Expand Up @@ -75,83 +135,16 @@
@click="toggleMenu"
>
<FontAwesomeIcon :icon="showMenu ? 'caret-up' : 'caret-down'" />
<span class="ms-1">{{ $t(showMenu ? 'close_menu' : 'open_menu') }}</span>
<span class="ms-1">{{
i18n.t(showMenu ? 'close_menu' : 'open_menu')
}}</span>
</button>
</div>
</transition>
</div>
</div>
</template>

<script>
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { mapActions, mapGetters, mapState } from 'vuex'

import BlackBackdrop from '@/modules/menu/components/BlackBackdrop.vue'
import DebugToolbar from '@/modules/menu/components/debug/DebugToolbar.vue'
import HeaderWithSearch from '@/modules/menu/components/header/HeaderWithSearch.vue'
import MenuTray from '@/modules/menu/components/menu/MenuTray.vue'
import TimeSlider from '@/modules/menu/components/timeslider/TimeSlider.vue'
import FullScreenButton from '@/modules/menu/components/toolboxRight/FullScreenButton.vue'
import GeolocButton from '@/modules/menu/components/toolboxRight/GeolocButton.vue'
import TimeSliderButton from '@/modules/menu/components/toolboxRight/TimeSliderButton.vue'
import Toggle3dButton from '@/modules/menu/components/toolboxRight/Toggle3dButton.vue'
import ZoomButtons from '@/modules/menu/components/toolboxRight/ZoomButtons.vue'

export default {
components: {
FullScreenButton,
DebugToolbar,
Toggle3dButton,
FontAwesomeIcon,
TimeSlider,
TimeSliderButton,
HeaderWithSearch,
BlackBackdrop,
ZoomButtons,
GeolocButton,
MenuTray,
},
data() {
return {
showTimeSlider: false,
}
},
computed: {
...mapState({
isGeolocationActive: (state) => state.geolocation.active,
isGeolocationDenied: (state) => state.geolocation.denied,
showMenu: (state) => state.ui.showMenu,
isFullscreenMode: (state) => state.ui.fullscreenMode,
isEmbedded: (state) => state.ui.embeddedMode,
previewYear: (state) => state.layers.previewYear,
inDrawingMode: (state) => state.ui.showDrawingOverlay,
}),
...mapGetters([
'isHeaderShown',
'isPhoneMode',
'isDesktopMode',
'isMenuShown',
'isMenuTrayShown',
'hasDevSiteWarning',
'visibleLayers',
'visibleLayersWithTimeConfig',
]),
},
watch: {
previewYear() {
// hiding the time slider if the preview has been cleared
if (!this.previewYear) {
this.showTimeSlider = false
}
},
},
methods: {
...mapActions(['toggleGeolocation', 'increaseZoom', 'decreaseZoom', 'toggleMenu']),
},
}
</script>

<style lang="scss" scoped>
@import 'src/scss/media-query.mixin';
@import 'src/scss/variables';
Expand Down
6 changes: 5 additions & 1 deletion src/store/plugins/sync-camera-lonlatzoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import { WGS84 } from '@/utils/coordinates/coordinateSystems'
*/
export default function syncCameraLonLatZoom(store) {
store.subscribe((mutation, state) => {
if (mutation.type === 'setCameraPosition' && state.position.camera !== null) {
// only reacting to mutation when the camera is set (when 3D is active and loaded)
if (state.position.camera === null) {
return
}
if (mutation.type === 'setCameraPosition') {
const lon = parseFloat(state.position.camera.x)
const lat = parseFloat(state.position.camera.y)
const height = parseFloat(state.position.camera.z)
Expand Down