优化馆内楼层切换展示
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user