Merge branch 'dev' of http://222.212.85.86:8222/bdzl2/bxztApp into dev
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 846 KiB |
|
After Width: | Height: | Size: 911 KiB |
@ -82,7 +82,7 @@ const locationInfo = [
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
grid-template-rows: repeat(2, minmax(0, 1fr));
|
||||
gap: clamp(10px, vh(14), 18px) clamp(12px, vw(16), 20px);
|
||||
gap: clamp(4px, vh(6), 8px) clamp(4px, vw(6), 8px);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
@ -91,7 +91,7 @@ const locationInfo = [
|
||||
.info-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: clamp(8px, vw(12), 14px);
|
||||
gap: 3px;
|
||||
// padding: clamp(10px, vh(12), 16px) clamp(12px, vw(14), 18px);
|
||||
// background: rgba(10, 95, 165, 0.15);
|
||||
border-radius: clamp(6px, vw(8), 10px);
|
||||
@ -137,9 +137,9 @@ const locationInfo = [
|
||||
// 值样式
|
||||
.info-value {
|
||||
margin: 0;
|
||||
font-size: clamp(15px, vw(18), 22px);
|
||||
font-size: 12px;
|
||||
color: #e8f4ff;
|
||||
font-weight: 600;
|
||||
// font-weight: 600;
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="left-panel-wrapper">
|
||||
<div class="left-panel">
|
||||
<CollapsiblePanel title="快速感知" subtitle="「灾害分析」">
|
||||
<template #header-right>
|
||||
<template #title-icon>
|
||||
<img
|
||||
src="../../assets/images/摄像头.png"
|
||||
alt="摄像头"
|
||||
@ -96,10 +96,11 @@ const handleStartDispatch = (payload) => {
|
||||
.left-panel {
|
||||
// width: vw(464);
|
||||
height: 100%;
|
||||
background: url('../../assets/images/SketchPng7ba5c49d9f8f79e6b559d62cfb6b0b0c79616dd8b289f8b62b5cb8adc18c30e7.png') no-repeat;
|
||||
background: url('../../assets/images/框架左边.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
padding-left: vw(40); // 为左侧折叠按钮预留空间
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: vw(6);
|
||||
@ -128,7 +129,7 @@ const handleStartDispatch = (payload) => {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: vh(12);
|
||||
width: vw(368);
|
||||
width: vw(220);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
@ -187,11 +188,12 @@ const handleStartDispatch = (payload) => {
|
||||
}
|
||||
|
||||
.camera-icon {
|
||||
width: vw(24);
|
||||
height: vw(24);
|
||||
margin-right: vw(8);
|
||||
width: vw(20);
|
||||
height: vw(20);
|
||||
margin-left: vw(6);
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s ease;
|
||||
vertical-align: middle;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
|
||||
@ -31,9 +31,9 @@
|
||||
<span class="col-name">{{ item.name }}</span>
|
||||
<span class="col-dept">{{ item.department || item.type || '-' }}</span>
|
||||
<span class="col-location">{{ item.distance || item.altitude || '-' }}</span>
|
||||
<button class="col-action" @click="linkToItem(item)">
|
||||
<span class="col-action" @click="linkToItem(item)">
|
||||
联动
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -127,7 +127,8 @@ const getColumnName = (type) => {
|
||||
}
|
||||
|
||||
.table-body {
|
||||
max-height: vh(200);
|
||||
min-height: vh(205);
|
||||
max-height: vh(205);
|
||||
overflow-y: auto;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
@ -165,15 +166,15 @@ const getColumnName = (type) => {
|
||||
.col-action {
|
||||
padding: vh(4) vw(12);
|
||||
background: transparent;
|
||||
border: 1px solid var(--primary-color);
|
||||
border-radius: vw(4);
|
||||
// border: 1px solid var(--primary-color);
|
||||
// border-radius: vw(4);
|
||||
color: var(--primary-color);
|
||||
font-size: fs(12);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
background: var(--primary-color);
|
||||
// background: var(--primary-color);
|
||||
color: var(--text-white);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
<template>
|
||||
<div class="video-monitor-item">
|
||||
<div class="video-monitor-item__header">
|
||||
<div class="video-monitor-item" :class="{ 'is-collapsed': isCollapsed }">
|
||||
<div class="video-monitor-item__header" @click="toggleCollapse">
|
||||
<span class="video-title">{{ monitor.title }}</span>
|
||||
<img
|
||||
src="../../assets/images/展开icon.png"
|
||||
alt="collapse"
|
||||
class="collapse-icon"
|
||||
:class="{ 'is-collapsed': isCollapsed }"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="video-monitor-item__content">
|
||||
<transition name="collapse">
|
||||
<div v-show="!isCollapsed" class="video-monitor-item__content">
|
||||
<div class="video-placeholder">
|
||||
<!-- 视频播放器 -->
|
||||
<video
|
||||
@ -77,6 +79,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -92,6 +95,16 @@ const props = defineProps({
|
||||
|
||||
defineEmits(['megaphone', 'audio', 'zoom'])
|
||||
|
||||
// 收起/展开状态
|
||||
const isCollapsed = ref(false)
|
||||
|
||||
/**
|
||||
* 切换收起/展开状态
|
||||
*/
|
||||
const toggleCollapse = () => {
|
||||
isCollapsed.value = !isCollapsed.value
|
||||
}
|
||||
|
||||
const currentTime = ref('')
|
||||
|
||||
const updateTime = () => {
|
||||
@ -132,6 +145,13 @@ onUnmounted(() => {
|
||||
padding: 2px;
|
||||
// border-radius: vw(8);
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
// 收起状态:只显示标题栏
|
||||
&.is-collapsed {
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
@ -140,6 +160,7 @@ onUnmounted(() => {
|
||||
padding: vh(10) vw(16);
|
||||
background: rgba(20, 53, 118, 0.5);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
.video-title {
|
||||
color: var(--text-white);
|
||||
@ -152,11 +173,30 @@ onUnmounted(() => {
|
||||
width: vw(26);
|
||||
height: vw(26);
|
||||
cursor: pointer;
|
||||
transition: transform 0.3s;
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
// &:hover {
|
||||
// transform: rotate(180deg);
|
||||
// }
|
||||
&.is-collapsed {
|
||||
// transform: rotate(180deg);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 收起状态下的 header 样式
|
||||
&.is-collapsed &__header {
|
||||
border-bottom: none;
|
||||
border-radius: vw(8);
|
||||
}
|
||||
|
||||
&__header {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
background: rgba(20, 53, 118, 0.7);
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,4 +306,23 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 折叠动画
|
||||
.collapse-enter-active,
|
||||
.collapse-leave-active {
|
||||
transition: all 0.3s ease;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.collapse-enter-from,
|
||||
.collapse-leave-to {
|
||||
max-height: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.collapse-enter-to,
|
||||
.collapse-leave-from {
|
||||
max-height: 500px;
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -36,10 +36,11 @@ import CollaborationInfo from './CollaborationInfo.vue'
|
||||
.right-panel {
|
||||
// width: vw(486);
|
||||
height: 100%;
|
||||
background: url('../../assets/images/SketchPngab2bc23b7e477ddbee76b880e28c1c97d6afb9261784dec29ed08c4e0a34d5b3.png') no-repeat;
|
||||
background: url('../../assets/images/框架右边.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
padding-right: vw(40); // 为右侧折叠按钮预留空间
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: vw(6);
|
||||
|
||||
@ -6,6 +6,9 @@
|
||||
@click="collapsible && toggle()"
|
||||
>
|
||||
<PanelHeader :title="title" :subtitle="subtitle">
|
||||
<template #title-icon>
|
||||
<slot name="title-icon" />
|
||||
</template>
|
||||
<template #extra>
|
||||
<slot name="header-right" />
|
||||
<button
|
||||
@ -16,20 +19,12 @@
|
||||
:aria-label="isCollapsed ? '展开面板' : '收起面板'"
|
||||
@click.stop="toggle"
|
||||
>
|
||||
<svg
|
||||
<img
|
||||
:src="toggleIcon"
|
||||
alt=""
|
||||
class="collapsible-panel__toggle-icon"
|
||||
:class="{ 'is-collapsed': isCollapsed }"
|
||||
viewBox="0 0 12 12"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M3 5L6 8L9 5"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
/>
|
||||
</button>
|
||||
</template>
|
||||
</PanelHeader>
|
||||
@ -56,6 +51,7 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue'
|
||||
import PanelHeader from './PanelHeader.vue'
|
||||
import toggleIcon from '../../assets/images/展开icon.png'
|
||||
|
||||
const props = defineProps({
|
||||
/** 面板标题 */
|
||||
@ -196,13 +192,12 @@ function onAfterLeave(el) {
|
||||
}
|
||||
|
||||
&__toggle-icon {
|
||||
width: vw(12);
|
||||
height: vh(12);
|
||||
color: var(--primary-color);
|
||||
width: vw(24);
|
||||
height: auto;
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
&.is-collapsed {
|
||||
transform: rotate(-90deg);
|
||||
// transform: rotate(-90deg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
<div class="panel-header__content">
|
||||
<span class="panel-header__title">{{ title }}</span>
|
||||
<span v-if="subtitle" class="panel-header__subtitle">{{ subtitle }}</span>
|
||||
<slot name="title-icon"></slot>
|
||||
</div>
|
||||
<slot name="extra"></slot>
|
||||
</div>
|
||||
|
||||
@ -69,7 +69,8 @@ export const BEFORE_IMAGERY_CONFIG = {
|
||||
// 影像服务URL
|
||||
// 格式:支持标准瓦片服务的URL模板,{z}/{x}/{y} 为瓦片坐标占位符
|
||||
// url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
|
||||
// url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
|
||||
url: 'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/model/ylzg/zxyj1119/terra_b3dms/tileset.json',
|
||||
|
||||
// 图层类型
|
||||
type: 'UrlTemplate',
|
||||
|
||||
@ -26,8 +26,13 @@
|
||||
<div class="situational-awareness__right-map">
|
||||
<MapViewer @tool-change="handleMapToolChange" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 场景标签层 -->
|
||||
<!-- 地图遮罩层 -->
|
||||
<div class="situational-awareness__map-mask" aria-hidden="true"></div>
|
||||
|
||||
<!-- 场景标签层 - 独立层级,显示在遮罩层之上 -->
|
||||
<div class="situational-awareness__scene-labels-layer">
|
||||
<!-- 灾前现场实景标签 - 在中间分割线左侧 -->
|
||||
<SceneLabel
|
||||
v-if="isCompareMode"
|
||||
@ -42,25 +47,56 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 地图遮罩层 -->
|
||||
<div class="situational-awareness__map-mask" aria-hidden="true"></div>
|
||||
|
||||
<!-- 浮动面板层 -->
|
||||
<div class="situational-awareness__panels-layer">
|
||||
<div
|
||||
class="situational-awareness__panel-column situational-awareness__panel-column--left"
|
||||
<Transition name="panel-slide-left">
|
||||
<div
|
||||
v-show="!isLeftPanelCollapsed"
|
||||
class="situational-awareness__panel-column situational-awareness__panel-column--left"
|
||||
>
|
||||
<LeftPanel @start-dispatch="handleStartDispatch" />
|
||||
</div>
|
||||
</Transition>
|
||||
|
||||
<Transition name="panel-slide-right">
|
||||
<div
|
||||
v-show="!isRightPanelCollapsed"
|
||||
class="situational-awareness__panel-column situational-awareness__panel-column--right"
|
||||
>
|
||||
<RightPanel />
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
|
||||
<!-- 折叠按钮层 -->
|
||||
<div class="situational-awareness__collapse-buttons-layer">
|
||||
<!-- 左侧折叠按钮 -->
|
||||
<button
|
||||
class="situational-awareness__collapse-btn situational-awareness__collapse-btn--left"
|
||||
:class="{ 'is-collapsed': isLeftPanelCollapsed }"
|
||||
@click="toggleLeftPanel"
|
||||
:aria-label="isLeftPanelCollapsed ? '展开左侧面板' : '收起左侧面板'"
|
||||
>
|
||||
<LeftPanel @start-dispatch="handleStartDispatch" />
|
||||
</div>
|
||||
<div
|
||||
class="situational-awareness__center-spacer"
|
||||
aria-hidden="true"
|
||||
></div>
|
||||
<div
|
||||
class="situational-awareness__panel-column situational-awareness__panel-column--right"
|
||||
<img
|
||||
:src="isLeftPanelCollapsed ? collapseRightArrow : collapseLeftArrow"
|
||||
alt=""
|
||||
class="collapse-arrow"
|
||||
/>
|
||||
</button>
|
||||
|
||||
<!-- 右侧折叠按钮 -->
|
||||
<button
|
||||
class="situational-awareness__collapse-btn situational-awareness__collapse-btn--right"
|
||||
:class="{ 'is-collapsed': isRightPanelCollapsed }"
|
||||
@click="toggleRightPanel"
|
||||
:aria-label="isRightPanelCollapsed ? '展开右侧面板' : '收起右侧面板'"
|
||||
>
|
||||
<RightPanel />
|
||||
</div>
|
||||
<img
|
||||
:src="isRightPanelCollapsed ? collapseLeftArrow : collapseRightArrow"
|
||||
alt=""
|
||||
class="collapse-arrow"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 地图控件层 - 高于遮罩和面板 -->
|
||||
@ -146,6 +182,10 @@ import soldierIcon from "./assets/images/SketchPngfbec927027ff9e49207749ebaafd22
|
||||
import deviceIcon from "./assets/images/SketchPng860d54f2a31f5f441fc6a88081224f1e98534bf6d5ca1246e420983bdf690380.png";
|
||||
import emergencyBaseIcon from "./assets/images/应急基地.png";
|
||||
|
||||
// 折叠按钮图标
|
||||
import collapseLeftArrow from "./assets/images/折叠面板左箭头.png";
|
||||
import collapseRightArrow from "./assets/images/折叠面板右箭头.png";
|
||||
|
||||
// 使用灾害数据
|
||||
const disasterData = useDisasterData();
|
||||
|
||||
@ -196,6 +236,20 @@ const showLoading = ref(false);
|
||||
// 范围圈实体
|
||||
const rangeCircleEntity = ref(null);
|
||||
|
||||
// 面板折叠状态
|
||||
const isLeftPanelCollapsed = ref(false);
|
||||
const isRightPanelCollapsed = ref(false);
|
||||
|
||||
// 切换左侧面板
|
||||
const toggleLeftPanel = () => {
|
||||
isLeftPanelCollapsed.value = !isLeftPanelCollapsed.value;
|
||||
};
|
||||
|
||||
// 切换右侧面板
|
||||
const toggleRightPanel = () => {
|
||||
isRightPanelCollapsed.value = !isRightPanelCollapsed.value;
|
||||
};
|
||||
|
||||
// 3D Tiles加载功能
|
||||
const { load3DTileset, waitForTilesetReady } = use3DTiles();
|
||||
|
||||
@ -216,6 +270,48 @@ const setupMapClickHandler = (viewer) => {
|
||||
if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
|
||||
const entity = pickedObject.id;
|
||||
|
||||
// 过滤掉范围圈实体(通过检查是否是范围圈)
|
||||
if (entity === rangeCircleEntity.value) {
|
||||
console.log('[index.vue] 点击了范围圈,忽略');
|
||||
// 尝试穿透到下面的实体
|
||||
const drillPickedObjects = viewer.scene.drillPick(click.position);
|
||||
let foundMarker = false;
|
||||
|
||||
for (const pickedObj of drillPickedObjects) {
|
||||
if (Cesium.defined(pickedObj.id) && pickedObj.id !== rangeCircleEntity.value) {
|
||||
const markerEntity = pickedObj.id;
|
||||
if (markerEntity.properties) {
|
||||
const type = markerEntity.properties.type?.getValue();
|
||||
|
||||
// 找到标记点,显示 Tooltip
|
||||
if (type === 'soldier') {
|
||||
showMarkerTooltip(viewer, markerEntity, click.position, soldierIcon);
|
||||
foundMarker = true;
|
||||
break;
|
||||
} else if (type === 'device') {
|
||||
showMarkerTooltip(viewer, markerEntity, click.position, deviceIcon);
|
||||
foundMarker = true;
|
||||
break;
|
||||
} else if (type === 'emergencyBase' || type === 'station') {
|
||||
const stationName = markerEntity.properties.name?.getValue() || '';
|
||||
const icon = stationName === '忠县公路交通应急物资储备中心'
|
||||
? emergencyCenterIcon
|
||||
: emergencyBaseIcon;
|
||||
showMarkerTooltip(viewer, markerEntity, click.position, icon);
|
||||
foundMarker = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundMarker) {
|
||||
hideTooltip();
|
||||
currentTooltipEntity.value = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查实体是否有 properties(标记点才有)
|
||||
if (entity.properties) {
|
||||
const type = entity.properties.type?.getValue();
|
||||
@ -769,6 +865,11 @@ const createOrUpdateRangeCircle = (viewer, radiusKm) => {
|
||||
}
|
||||
});
|
||||
|
||||
// 禁用范围圈的鼠标交互,让点击可以穿透到下面的标记点
|
||||
if (rangeCircleEntity.value) {
|
||||
rangeCircleEntity.value.allowPicking = false;
|
||||
}
|
||||
|
||||
console.log(`[index.vue] 已创建/更新范围圈: ${radiusKm}km`);
|
||||
};
|
||||
|
||||
@ -950,7 +1051,9 @@ const showMapTooltip = ({ x, y, title = "", icon = "", data = null }) => {
|
||||
|
||||
.situational-awareness__left-map {
|
||||
width: 0;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@ -958,8 +1061,9 @@ const showMapTooltip = ({ x, y, title = "", icon = "", data = null }) => {
|
||||
&.is-compare-mode {
|
||||
.situational-awareness__left-map {
|
||||
width: 50%;
|
||||
visibility: visible;
|
||||
transition: width 0.3s ease;
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
transition: width 0.3s ease, opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.situational-awareness__right-map {
|
||||
@ -1010,28 +1114,46 @@ const showMapTooltip = ({ x, y, title = "", icon = "", data = null }) => {
|
||||
no-repeat;
|
||||
}
|
||||
|
||||
// 浮动面板层 - grid 与 pointer-events 结合保证中间透明
|
||||
// 场景标签层 - 显示在遮罩层和面板层之上
|
||||
&__scene-labels-layer {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 10;
|
||||
pointer-events: none; // 标签不阻挡交互
|
||||
}
|
||||
|
||||
// 浮动面板层 - 使用绝对定位固定面板位置
|
||||
&__panels-layer {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 2;
|
||||
display: grid;
|
||||
grid-template-columns: var(--sa-left-width) 1fr var(--sa-right-width);
|
||||
grid-auto-rows: 1fr;
|
||||
gap: var(--sa-gap); // 列之间的间距
|
||||
height: 100%;
|
||||
padding-top: var(--sa-header-height); // 预留 Header 高度
|
||||
pointer-events: none; // 容器不拦截事件,让中间区域透明
|
||||
}
|
||||
|
||||
// 左右面板列 - 浮动卡片样式
|
||||
&__panel-column {
|
||||
position: absolute;
|
||||
top: var(--sa-header-height); // 从 header 下方开始
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--sa-gap); // 列内子面板之间的间距
|
||||
min-width: 0; // 防止在窄容器中溢出
|
||||
min-height: 0; // 允许 flex 子元素收缩并启用滚动
|
||||
pointer-events: auto; // 恢复面板的交互能力
|
||||
|
||||
// 左侧面板固定在左边
|
||||
&--left {
|
||||
left: 0;
|
||||
width: var(--sa-left-width);
|
||||
}
|
||||
|
||||
// 右侧面板固定在右边
|
||||
&--right {
|
||||
right: 0;
|
||||
width: var(--sa-right-width);
|
||||
}
|
||||
}
|
||||
|
||||
// 中间占位区域 - 透明且不可交互,点击穿透到地图
|
||||
@ -1039,6 +1161,88 @@ const showMapTooltip = ({ x, y, title = "", icon = "", data = null }) => {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
// 折叠按钮层 - 独立层级,放置在屏幕两侧
|
||||
&__collapse-buttons-layer {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 11; // 高于场景标签层
|
||||
pointer-events: none; // 容器不拦截事件
|
||||
padding-top: var(--sa-header-height); // 预留 Header 高度
|
||||
}
|
||||
|
||||
// 折叠按钮
|
||||
&__collapse-btn {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s ease;
|
||||
z-index: 11;
|
||||
padding: 0;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: translateY(-50%) scale(0.95);
|
||||
}
|
||||
|
||||
.collapse-arrow {
|
||||
width: vw(30);
|
||||
height: auto;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
// 左侧按钮 - 固定在屏幕最左侧
|
||||
&--left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
// 右侧按钮 - 固定在屏幕最右侧
|
||||
&--right {
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 面板滑动动画 - 左侧
|
||||
.panel-slide-left-enter-active,
|
||||
.panel-slide-left-leave-active {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.panel-slide-left-enter-from {
|
||||
transform: translateX(-100%);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.panel-slide-left-leave-to {
|
||||
transform: translateX(-100%);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
// 面板滑动动画 - 右侧
|
||||
.panel-slide-right-enter-active,
|
||||
.panel-slide-right-leave-active {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.panel-slide-right-enter-from {
|
||||
transform: translateX(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.panel-slide-right-leave-to {
|
||||
transform: translateX(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
// 地图控件层 - 高于遮罩和面板,用于放置地图控制工具
|
||||
&__controls-layer {
|
||||
position: absolute;
|
||||
|
||||