优化馆内楼层切换展示

This commit is contained in:
lyf
2026-07-04 18:50:08 +08:00
parent e813660aea
commit 5a61357f63
2 changed files with 63 additions and 96 deletions

View File

@@ -1,6 +1,12 @@
<template> <template>
<view class="floor-switcher"> <view class="floor-switcher">
<view class="floor-list"> <view
class="floor-list"
:class="{
compact: floors.length >= 8,
dense: floors.length >= 10
}"
>
<view <view
v-for="floor in floors" v-for="floor in floors"
:key="floor.id" :key="floor.id"
@@ -70,22 +76,33 @@ const handleFloorTap = (floorId: string) => {
.floor-list { .floor-list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 6px; gap: 4px;
background-color: rgba(26, 26, 46, 0.9); background-color: rgba(26, 26, 46, 0.9);
border-radius: 12px; border-radius: 10px;
padding: 8px; padding: 6px;
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.1);
overflow: visible;
}
.floor-list.compact {
gap: 3px;
padding: 5px;
}
.floor-list.dense {
gap: 2px;
padding: 4px;
} }
.floor-item { .floor-item {
width: 52px; width: 46px;
height: 48px; height: 34px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 4px; gap: 3px;
background-color: transparent; background-color: transparent;
border-radius: 8px; border-radius: 8px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
@@ -97,16 +114,27 @@ const handleFloorTap = (floorId: string) => {
} }
} }
.floor-list.compact .floor-item {
width: 44px;
height: 30px;
}
.floor-list.dense .floor-item {
width: 42px;
height: 28px;
}
.floor-indicator { .floor-indicator {
width: 24px; width: 20px;
height: 3px; height: 2px;
background-color: rgba(255, 255, 255, 0.3); background-color: rgba(255, 255, 255, 0.3);
border-radius: 2px; border-radius: 2px;
transition: all 0.3s ease; transition: all 0.3s ease;
} }
.floor-label { .floor-label {
font-size: 14px; font-size: 12px;
line-height: 16px;
font-weight: 600; font-weight: 600;
color: rgba(255, 255, 255, 0.6); color: rgba(255, 255, 255, 0.6);
transition: all 0.3s ease; transition: all 0.3s ease;
@@ -117,7 +145,7 @@ const handleFloorTap = (floorId: string) => {
background-color: rgba(224, 225, 0, 0.15); background-color: rgba(224, 225, 0, 0.15);
.floor-indicator { .floor-indicator {
width: 32px; width: 28px;
background-color: #E0E100; background-color: #E0E100;
box-shadow: 0 0 8px rgba(224, 225, 0, 0.5); box-shadow: 0 0 8px rgba(224, 225, 0, 0.5);
} }
@@ -143,8 +171,8 @@ const handleFloorTap = (floorId: string) => {
// 3D 视角指示器 // 3D 视角指示器
.view-indicator { .view-indicator {
width: 52px; width: 46px;
height: 28px; height: 24px;
background: linear-gradient(135deg, #E0E100 0%, #c4c400 100%); background: linear-gradient(135deg, #E0E100 0%, #c4c400 100%);
border-radius: 6px; border-radius: 6px;
display: flex; display: flex;
@@ -153,7 +181,7 @@ const handleFloorTap = (floorId: string) => {
box-shadow: 0 2px 8px rgba(224, 225, 0, 0.4); box-shadow: 0 2px 8px rgba(224, 225, 0, 0.4);
.view-icon { .view-icon {
font-size: 12px; font-size: 11px;
font-weight: 700; font-weight: 700;
color: #000000; color: #000000;
letter-spacing: 0.5px; letter-spacing: 0.5px;

View File

@@ -141,17 +141,11 @@
<text class="floor-header-icon"></text> <text class="floor-header-icon"></text>
<text class="floor-header-label">{{ layerModeActionLabel }}</text> <text class="floor-header-label">{{ layerModeActionLabel }}</text>
</view> </view>
<scroll-view <view
class="floor-list" class="floor-list"
:style="floorListStyle"
scroll-y
:show-scrollbar="false"
:scroll-into-view="activeFloorScrollIntoView"
:scroll-with-animation="true"
> >
<view <view
v-for="floor in floorItems" v-for="floor in floorItems"
:id="floor.scrollId"
:key="floor.id" :key="floor.id"
class="floor-item" class="floor-item"
:class="{ :class="{
@@ -164,7 +158,7 @@
> >
<text class="floor-label">{{ floor.label }}</text> <text class="floor-label">{{ floor.label }}</text>
</view> </view>
</scroll-view> </view>
</view> </view>
<view v-if="showZoomControls" class="zoom-controls" :style="zoomControlsStyle"> <view v-if="showZoomControls" class="zoom-controls" :style="zoomControlsStyle">
@@ -437,11 +431,7 @@ const indoorRendererRef = ref<{
} | null>(null) } | null>(null)
const indoorFloors = computed(() => props.floors.filter((floor) => isIndoorNavigableFloor(floor))) const indoorFloors = computed(() => props.floors.filter((floor) => isIndoorNavigableFloor(floor)))
const createFloorScrollId = (floorId: string) => `guide-floor-${floorId.replace(/[^a-zA-Z0-9_-]/g, '-')}` const floorItems = computed(() => indoorFloors.value)
const floorItems = computed(() => indoorFloors.value.map((floor) => ({
...floor,
scrollId: createFloorScrollId(floor.id)
})))
// #ifdef H5 // #ifdef H5
const effectiveIndoorModelSource = computed(() => props.indoorModelSource) const effectiveIndoorModelSource = computed(() => props.indoorModelSource)
// #endif // #endif
@@ -461,7 +451,6 @@ const activeFloorId = computed(() => {
)) ))
return normalizedFloor?.id || normalizedFloorId return normalizedFloor?.id || normalizedFloorId
}) })
const activeFloorScrollIntoView = ref('')
const requestedFloorId = ref('') const requestedFloorId = ref('')
const requestedFloorLabel = ref('') const requestedFloorLabel = ref('')
const loadingFloorId = ref('') const loadingFloorId = ref('')
@@ -469,38 +458,8 @@ const renderedFloorId = ref(activeFloorId.value)
const activeFloorSwitchRequestSeq = ref(0) const activeFloorSwitchRequestSeq = ref(0)
const renderedFloorSwitchRequestSeq = ref(0) const renderedFloorSwitchRequestSeq = ref(0)
const failedFloorId = ref('') const failedFloorId = ref('')
let suppressFloorAutoScrollForFloorId = ''
let floorSwitchRequestSeq = 0 let floorSwitchRequestSeq = 0
const syncActiveFloorScroll = () => {
if (props.mapType !== 'indoor' || props.indoorView === 'overview' || props.layerMode === 'multi') {
activeFloorScrollIntoView.value = ''
return
}
if (activeFloorId.value === suppressFloorAutoScrollForFloorId) {
activeFloorScrollIntoView.value = ''
suppressFloorAutoScrollForFloorId = ''
return
}
suppressFloorAutoScrollForFloorId = ''
const matchedFloor = floorItems.value.find((floor) => floor.id === activeFloorId.value)
activeFloorScrollIntoView.value = matchedFloor?.scrollId || ''
}
watch(
() => [
activeFloorId.value,
props.indoorView,
props.layerMode,
props.mapType,
floorItems.value.map((floor) => floor.id).join('|')
],
syncActiveFloorScroll,
{ immediate: true }
)
const searchFieldStyle = computed(() => ({ const searchFieldStyle = computed(() => ({
top: props.searchTop top: props.searchTop
})) }))
@@ -509,12 +468,6 @@ const floorSwitcherStyle = computed(() => ({
...(props.floorBottom ? { bottom: props.floorBottom } : { top: props.floorTop }) ...(props.floorBottom ? { bottom: props.floorBottom } : { top: props.floorTop })
})) }))
const floorListStyle = computed(() => ({
...(props.floorMaxHeight
? { maxHeight: props.showFloorHeader ? `calc(${props.floorMaxHeight} - 50px)` : props.floorMaxHeight }
: {})
}))
const layerModeToggleStyle = computed(() => ({ const layerModeToggleStyle = computed(() => ({
top: props.layerModeToggleTop top: props.layerModeToggleTop
})) }))
@@ -606,8 +559,6 @@ const handleFloorChange = (floor: { id: string; label: string }) => {
const requestSeq = ++floorSwitchRequestSeq const requestSeq = ++floorSwitchRequestSeq
activeFloorSwitchRequestSeq.value = requestSeq activeFloorSwitchRequestSeq.value = requestSeq
failedFloorId.value = '' failedFloorId.value = ''
suppressFloorAutoScrollForFloorId = floorId
activeFloorScrollIntoView.value = ''
indoorRendererRef.value?.disableAutoSwitchTemporarily?.(10000) indoorRendererRef.value?.disableAutoSwitchTemporarily?.(10000)
emit('floorRequest', { emit('floorRequest', {
floorId, floorId,
@@ -1067,12 +1018,11 @@ defineExpose({
.floor-switcher { .floor-switcher {
position: absolute; position: absolute;
width: 46px; width: 44px;
height: auto; height: auto;
padding: 1px; padding: 1px;
box-sizing: border-box; box-sizing: border-box;
overflow: hidden; overflow: hidden;
scrollbar-width: none;
background: rgba(255, 255, 255, 0.84); background: rgba(255, 255, 255, 0.84);
border: 1px solid #dde5df; border: 1px solid #dde5df;
border-radius: 8px; border-radius: 8px;
@@ -1080,21 +1030,10 @@ defineExpose({
z-index: 35; z-index: 35;
} }
.floor-switcher::-webkit-scrollbar {
display: none;
}
.floor-list { .floor-list {
max-height: calc(100vh - 310px); display: flex;
overflow-y: auto; flex-direction: column;
overscroll-behavior: contain; overflow: visible;
-webkit-overflow-scrolling: touch;
touch-action: pan-y;
scrollbar-width: none;
}
.floor-list::-webkit-scrollbar {
display: none;
} }
.floor-switcher.side-right { .floor-switcher.side-right {
@@ -1107,8 +1046,8 @@ defineExpose({
.floor-header { .floor-header {
position: relative; position: relative;
min-height: 50px; min-height: 38px;
padding: 7px 4px 6px; padding: 5px 4px 4px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
@@ -1134,8 +1073,8 @@ defineExpose({
} }
.floor-header-icon { .floor-header-icon {
width: 18px; width: 16px;
height: 18px; height: 16px;
position: relative; position: relative;
display: block; display: block;
color: #151713; color: #151713;
@@ -1155,15 +1094,15 @@ defineExpose({
.floor-header-icon::before { .floor-header-icon::before {
left: 2px; left: 2px;
top: 4px; top: 4px;
width: 12px; width: 11px;
height: 10px; height: 9px;
} }
.floor-header-icon::after { .floor-header-icon::after {
left: 5px; left: 5px;
top: 1px; top: 1px;
width: 12px; width: 11px;
height: 10px; height: 9px;
background: #ffffff; background: #ffffff;
} }
@@ -1172,8 +1111,8 @@ defineExpose({
} }
.floor-header-label { .floor-header-label {
font-size: 11px; font-size: 10px;
line-height: 14px; line-height: 12px;
color: #545861; color: #545861;
} }
@@ -1210,7 +1149,7 @@ defineExpose({
.floor-item { .floor-item {
position: relative; position: relative;
height: 36px; height: 30px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -1247,7 +1186,7 @@ defineExpose({
.floor-item.pending::before { .floor-item.pending::before {
content: ''; content: '';
position: absolute; position: absolute;
inset: 7px; inset: 5px;
border: 1px solid rgba(224, 225, 0, 0.9); border: 1px solid rgba(224, 225, 0, 0.9);
border-radius: 6px; border-radius: 6px;
} }
@@ -1262,8 +1201,8 @@ defineExpose({
} }
.floor-label { .floor-label {
font-size: 13px; font-size: 12px;
line-height: 18px; line-height: 16px;
font-weight: 500; font-weight: 500;
color: #545861; color: #545861;
} }