Skip to content
31 changes: 31 additions & 0 deletions app/components/CameraOrientation.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<script setup>
import GlassCard from "@ogw_front/components/GlassCard.vue";

const orientations = [
{ direction: "top", icon: "mdi-chevron-up", tooltip: "Top" },
{ direction: "bottom", icon: "mdi-chevron-down", tooltip: "Bottom" },
{ direction: "north", icon: "mdi-chevron-left", tooltip: "North" },
{ direction: "south", icon: "mdi-chevron-right", tooltip: "South" },
{ direction: "east", icon: "mdi-chevron-left", tooltip: "East" },
{ direction: "west", icon: "mdi-chevron-right", tooltip: "West" },
];

const emit = defineEmits(["setOrientation"]);

function setOrientation(direction) {
emit("setOrientation", direction);
}
</script>

<template>
<GlassCard padding="pa-2">
<v-row dense>
<v-col v-for="orientation in orientations" :key="orientation.direction" cols="4">
<v-btn icon variant="text" @click="setOrientation(orientation.direction)">
<v-icon>{{ orientation.icon }}</v-icon>
<v-tooltip activator="parent" location="top">{{ orientation.tooltip }}</v-tooltip>
</v-btn>
</v-col>
</v-row>
</GlassCard>
</template>
18 changes: 17 additions & 1 deletion app/components/VeaseViewToolbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json";

import ActionButton from "@ogw_front/components/ActionButton.vue";
import CameraOrientationButtons from "@ogw_front/components/Viewer/CameraOrientationButtons.vue";
import Screenshot from "@ogw_front/components/Screenshot";
import ZScaling from "@ogw_front/components/ZScaling";

Expand Down Expand Up @@ -70,7 +71,22 @@ const camera_options = [

<template>
<v-container :class="[$style.floatToolbar, 'pa-0']" width="auto">
<v-row v-for="camera_option in camera_options" :key="camera_option.icon" dense>
<!-- First button: Reset camera -->
<v-row dense>
<v-col>
<ActionButton
:icon="camera_options[0].icon"
:tooltip="camera_options[0].tooltip"
@click.stop="camera_options[0].action"
/>
</v-col>
</v-row>

<!-- Second: Camera Orientations Menu -->
<CameraOrientationButtons />

<!-- Remaining options -->
<v-row v-for="camera_option in camera_options.slice(1)" :key="camera_option.icon" dense>
<v-col>
<ActionButton
:icon="camera_option.icon"
Expand Down
22 changes: 22 additions & 0 deletions app/components/ViewToolbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json";

import ActionButton from "@ogw_front/components/ActionButton.vue";
import CameraOrientation from "@ogw_front/components/CameraOrientation";
import Screenshot from "@ogw_front/components/Screenshot";
import { useViewerStore } from "@ogw_front/stores/viewer";

Expand All @@ -17,6 +18,11 @@ const camera_options = [
viewerStore.request(schemas.opengeodeweb_viewer.viewer.reset_camera);
},
},
{
tooltip: "Camera orientation",
icon: "mdi-axis-arrow",
menu: true,
},
{
tooltip: "Take a screenshot",
icon: "mdi-camera",
Expand All @@ -40,13 +46,29 @@ const camera_options = [
},
},
];

function setOrientation(direction) {
viewerStore.request(schemas.opengeodeweb_viewer.viewer.set_camera_orientation, { direction });
}
</script>

<template>
<v-container :class="[$style.floatToolbar, 'pa-0']" width="auto">
<v-row v-for="camera_option in camera_options" :key="camera_option.icon" dense>
<v-col>
<v-menu v-if="camera_option.menu" location="left" :close-on-content-click="false">
<template #activator="{ props }">
<ActionButton
v-bind="props"
:tooltip="camera_option.tooltip"
:icon="camera_option.icon"
tooltip-location="left"
/>
</template>
<CameraOrientation @set-orientation="setOrientation" />
</v-menu>
<ActionButton
v-else
:tooltip="camera_option.tooltip"
:icon="camera_option.icon"
tooltip-location="left"
Expand Down
93 changes: 93 additions & 0 deletions app/components/Viewer/CameraOrientationButtons.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<script setup>
import ActionButton from "@ogw_front/components/ActionButton.vue";
import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";

const hybridViewerStore = useHybridViewerStore();

const orientations = [
{ label: "Top", value: "top", tooltip: "Top View (+Z)", icon: "mdi-axis-z-arrow" },
{ label: "Bot", value: "bottom", tooltip: "Bottom View (-Z)", icon: "mdi-axis-z-arrow" },
{ label: "N", value: "north", tooltip: "North View (+Y)", icon: "mdi-axis-y-arrow" },
{ label: "S", value: "south", tooltip: "South View (-Y)", icon: "mdi-axis-y-arrow" },
{ label: "E", value: "east", tooltip: "East View (+X)", icon: "mdi-axis-x-arrow" },
{ label: "W", value: "west", tooltip: "West View (-X)", icon: "mdi-axis-x-arrow" },
];

function setOrientation(value) {
hybridViewerStore.setCameraOrientation(value);
}
</script>

<template>
<v-menu
location="left center"
transition="scale-transition"
:close-on-content-click="true"
offset="15"
>
<template #activator="{ props }">
<v-row dense>
<v-col>
<ActionButton v-bind="props" icon="mdi-axis-arrow" tooltip="Camera Orientations" />
</v-col>
</v-row>
</template>

<v-list density="compact" class="pa-2 orientation-menu" elevation="8" rounded="lg">
<v-row dense no-gutters>
<v-col v-for="opt in orientations" :key="opt.value" cols="4" class="pa-1">
<v-tooltip location="top">
<template #activator="{ props }">
<v-btn
v-bind="props"
icon
size="42"
variant="flat"
class="orientation-btn"
@click.stop="setOrientation(opt.value)"
>
<div class="d-flex flex-column align-center justify-center" style="gap: 2px">
<v-icon
size="18"
:style="opt.value === 'bottom' ? 'transform: rotate(180deg)' : ''"
>
{{ opt.icon }}
</v-icon>
<span :class="['text-label', opt.label.length > 1 ? 'text-label-condensed' : '']">
{{ opt.label }}
</span>
</div>
</v-btn>
</template>
<span>{{ opt.tooltip }}</span>
</v-tooltip>
</v-col>
</v-row>
</v-list>
</v-menu>
</template>

<style scoped>
.orientation-menu {
min-width: 160px;
background-color: rgb(var(--v-theme-surface)) !important;
}

.orientation-btn {
background-color: rgb(var(--v-theme-surface)) !important;
border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
border-radius: 50%;
}

.text-label {
font-size: 0.65rem !important;
font-weight: 900;
line-height: 1;
text-transform: uppercase;
}

.text-label-condensed {
font-size: 0.55rem !important;
letter-spacing: -0.8px !important;
}
</style>
Loading
Loading