Compare commits
No commits in common. "a1397c591fd3f4dfc264b05b0acca721bdbb5f6f" and "ed230e69ab06983090735f11147ecd5074497093" have entirely different histories.
a1397c591f
...
ed230e69ab
@ -11,15 +11,7 @@
|
|||||||
|
|
||||||
<div class="video-monitor-item__content">
|
<div class="video-monitor-item__content">
|
||||||
<div class="video-placeholder">
|
<div class="video-placeholder">
|
||||||
<!-- 视频播放器 -->
|
<!-- 这里放置实际的视频流组件 -->
|
||||||
<video
|
|
||||||
:src="monitor.videoSrc"
|
|
||||||
autoplay
|
|
||||||
loop
|
|
||||||
muted
|
|
||||||
playsinline
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div class="video-time">{{ currentTime }}</div>
|
<div class="video-time">{{ currentTime }}</div>
|
||||||
|
|
||||||
<!-- 控制条:叠加在视频底部 -->
|
<!-- 控制条:叠加在视频底部 -->
|
||||||
@ -172,15 +164,17 @@ onUnmounted(() => {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
// margin-bottom: vh(12);
|
// margin-bottom: vh(12);
|
||||||
|
|
||||||
// 视频元素
|
// 这里可以添加实际的视频组件
|
||||||
video {
|
&::before {
|
||||||
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 50%;
|
||||||
left: 0;
|
left: 50%;
|
||||||
width: 100%;
|
transform: translate(-50%, -50%);
|
||||||
height: 100%;
|
width: vw(48);
|
||||||
object-fit: cover;
|
height: vh(48);
|
||||||
z-index: 0;
|
background: url(../../assets/images/SketchPngb3b734375de691a8ba794eee7807988d78f942877ab220ebea0aac3bbddccd8b.png) center/contain no-repeat;
|
||||||
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-time {
|
.video-time {
|
||||||
|
|||||||
@ -7,8 +7,8 @@ import soldierIcon from '../assets/images/SketchPngfbec927027ff9e49207749ebaafd2
|
|||||||
import deviceIcon from '../assets/images/SketchPng860d54f2a31f5f441fc6a88081224f1e98534bf6d5ca1246e420983bdf690380.png'
|
import deviceIcon from '../assets/images/SketchPng860d54f2a31f5f441fc6a88081224f1e98534bf6d5ca1246e420983bdf690380.png'
|
||||||
import emergencyBaseIcon from '../assets/images/应急基地.png'
|
import emergencyBaseIcon from '../assets/images/应急基地.png'
|
||||||
|
|
||||||
// 默认高度偏移(米)- 与 WuRenJi 保持一致
|
// 默认高度偏移(米)
|
||||||
const DEFAULT_HEIGHT_OFFSET = 100
|
const DEFAULT_HEIGHT_OFFSET = 10
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 地图标记管理 Composable
|
* 地图标记管理 Composable
|
||||||
@ -136,18 +136,9 @@ export function useMapMarkers() {
|
|||||||
// 计算中心点
|
// 计算中心点
|
||||||
const center = Cesium.BoundingSphere.fromPoints(positions).center
|
const center = Cesium.BoundingSphere.fromPoints(positions).center
|
||||||
|
|
||||||
// 将中心点转换为经纬度,然后重新创建位置,确保高度为0
|
|
||||||
// 这样 CLAMP_TO_GROUND 才能正确工作
|
|
||||||
const centerCartographic = Cesium.Cartographic.fromCartesian(center)
|
|
||||||
const centerPosition = Cesium.Cartesian3.fromRadians(
|
|
||||||
centerCartographic.longitude,
|
|
||||||
centerCartographic.latitude,
|
|
||||||
0 // 高度设为0,让 CLAMP_TO_GROUND 自动贴地
|
|
||||||
)
|
|
||||||
|
|
||||||
// 添加标签
|
// 添加标签
|
||||||
const labelEntity = viewer.entities.add({
|
const labelEntity = viewer.entities.add({
|
||||||
position: centerPosition,
|
position: center,
|
||||||
label: {
|
label: {
|
||||||
text: '模拟塌陷区域',
|
text: '模拟塌陷区域',
|
||||||
font: '18px "Microsoft YaHei", sans-serif',
|
font: '18px "Microsoft YaHei", sans-serif',
|
||||||
@ -167,7 +158,7 @@ export function useMapMarkers() {
|
|||||||
|
|
||||||
// 添加中心点标记
|
// 添加中心点标记
|
||||||
const pointEntity = viewer.entities.add({
|
const pointEntity = viewer.entities.add({
|
||||||
position: centerPosition,
|
position: center,
|
||||||
point: {
|
point: {
|
||||||
color: Cesium.Color.ORANGE,
|
color: Cesium.Color.ORANGE,
|
||||||
pixelSize: 12,
|
pixelSize: 12,
|
||||||
@ -180,10 +171,6 @@ export function useMapMarkers() {
|
|||||||
|
|
||||||
collapseAreaEntities.value = entities
|
collapseAreaEntities.value = entities
|
||||||
console.log('[useMapMarkers] 塌陷区域绘制完成')
|
console.log('[useMapMarkers] 塌陷区域绘制完成')
|
||||||
|
|
||||||
// 强制渲染场景,确保 CLAMP_TO_GROUND 立即生效
|
|
||||||
viewer.scene.requestRender()
|
|
||||||
|
|
||||||
return center
|
return center
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,10 +291,6 @@ export function useMapMarkers() {
|
|||||||
|
|
||||||
markerEntities.value.push(...entities)
|
markerEntities.value.push(...entities)
|
||||||
console.log(`[useMapMarkers] 添加固定标记 ${entities.length} 个`)
|
console.log(`[useMapMarkers] 添加固定标记 ${entities.length} 个`)
|
||||||
|
|
||||||
// 强制渲染场景,确保 CLAMP_TO_GROUND 立即生效
|
|
||||||
viewer.scene.requestRender()
|
|
||||||
|
|
||||||
return entities
|
return entities
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,10 +387,6 @@ export function useMapMarkers() {
|
|||||||
|
|
||||||
markerEntities.value.push(...entities)
|
markerEntities.value.push(...entities)
|
||||||
console.log(`[useMapMarkers] 添加随机标记 ${entities.length} 个`)
|
console.log(`[useMapMarkers] 添加随机标记 ${entities.length} 个`)
|
||||||
|
|
||||||
// 强制渲染场景,确保 CLAMP_TO_GROUND 立即生效
|
|
||||||
viewer.scene.requestRender()
|
|
||||||
|
|
||||||
return entities
|
return entities
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,11 +627,6 @@ export function useMapMarkers() {
|
|||||||
|
|
||||||
emergencyResourceEntities.value = entities
|
emergencyResourceEntities.value = entities
|
||||||
console.log(`[useMapMarkers] 添加养护站标记 ${entities.length} 个`)
|
console.log(`[useMapMarkers] 添加养护站标记 ${entities.length} 个`)
|
||||||
|
|
||||||
// 强制渲染场景,确保 CLAMP_TO_GROUND 立即生效
|
|
||||||
if (entities.length > 0) {
|
|
||||||
viewer.scene.requestRender()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -1,63 +0,0 @@
|
|||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 地图 Tooltip 状态管理
|
|
||||||
* 用于显示地图标记点的轻量级信息提示框
|
|
||||||
*/
|
|
||||||
export function useMapTooltip() {
|
|
||||||
// Tooltip 状态
|
|
||||||
const tooltipState = ref({
|
|
||||||
visible: false,
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
title: '',
|
|
||||||
icon: '',
|
|
||||||
zIndex: 20,
|
|
||||||
data: null // 业务数据,用于内容插槽渲染
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 显示 Tooltip
|
|
||||||
* @param {Object} options - Tooltip 配置选项
|
|
||||||
* @param {number} options.x - 屏幕 X 坐标(像素)
|
|
||||||
* @param {number} options.y - 屏幕 Y 坐标(像素)
|
|
||||||
* @param {string} [options.title=''] - Tooltip 标题文本
|
|
||||||
* @param {string} [options.icon=''] - 标题左侧图标的图片路径
|
|
||||||
* @param {Object} [options.data=null] - 业务数据
|
|
||||||
*/
|
|
||||||
const showTooltip = ({ x, y, title = '', icon = '', data = null }) => {
|
|
||||||
tooltipState.value = {
|
|
||||||
visible: true,
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
title,
|
|
||||||
icon,
|
|
||||||
zIndex: 20,
|
|
||||||
data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 隐藏 Tooltip
|
|
||||||
*/
|
|
||||||
const hideTooltip = () => {
|
|
||||||
tooltipState.value.visible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新 Tooltip 位置
|
|
||||||
* @param {number} x - 屏幕 X 坐标
|
|
||||||
* @param {number} y - 屏幕 Y 坐标
|
|
||||||
*/
|
|
||||||
const updateTooltipPosition = (x, y) => {
|
|
||||||
tooltipState.value.x = x
|
|
||||||
tooltipState.value.y = y
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
tooltipState,
|
|
||||||
showTooltip,
|
|
||||||
hideTooltip,
|
|
||||||
updateTooltipPosition
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -2,8 +2,6 @@
|
|||||||
* 3D态势感知常量配置
|
* 3D态势感知常量配置
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getVideoUrl } from '@shared/utils'
|
|
||||||
|
|
||||||
// 视频监控视角类型
|
// 视频监控视角类型
|
||||||
export const VIDEO_TYPES = {
|
export const VIDEO_TYPES = {
|
||||||
PERSONNEL: 'personnel', // 单兵视角
|
PERSONNEL: 'personnel', // 单兵视角
|
||||||
@ -18,8 +16,7 @@ export const VIDEO_MONITORS = [
|
|||||||
id: 1,
|
id: 1,
|
||||||
type: VIDEO_TYPES.PERSONNEL,
|
type: VIDEO_TYPES.PERSONNEL,
|
||||||
title: '单兵(张三三)设备视角',
|
title: '单兵(张三三)设备视角',
|
||||||
// videoSrc: getVideoUrl('demo/ylzg/单兵视角.mp4'), // 从 OSS 获取视频 URL
|
videoSrc: '/videos/personnel-001.mp4', // 视频源路径
|
||||||
videoSrc: 'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/单兵视角.mp4',
|
|
||||||
dateRange: '2025/9/1-2025/12/1', // 日期范围
|
dateRange: '2025/9/1-2025/12/1', // 日期范围
|
||||||
hasAudio: true,
|
hasAudio: true,
|
||||||
hasMegaphone: true,
|
hasMegaphone: true,
|
||||||
@ -30,8 +27,7 @@ export const VIDEO_MONITORS = [
|
|||||||
id: 2,
|
id: 2,
|
||||||
type: VIDEO_TYPES.DRONE,
|
type: VIDEO_TYPES.DRONE,
|
||||||
title: '无人机(001)视角',
|
title: '无人机(001)视角',
|
||||||
// videoSrc: getVideoUrl('demo/ylzg/无人机视角.mp4'), // 从 OSS 获取视频 URL
|
videoSrc: '/videos/drone-001.mp4',
|
||||||
videoSrc: 'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/无人机视角.mp4',
|
|
||||||
dateRange: '2025/9/1-2025/12/1',
|
dateRange: '2025/9/1-2025/12/1',
|
||||||
hasAudio: false,
|
hasAudio: false,
|
||||||
hasMegaphone: true,
|
hasMegaphone: true,
|
||||||
@ -42,8 +38,7 @@ export const VIDEO_MONITORS = [
|
|||||||
id: 3,
|
id: 3,
|
||||||
type: VIDEO_TYPES.VEHICLE_EXTERNAL,
|
type: VIDEO_TYPES.VEHICLE_EXTERNAL,
|
||||||
title: '指挥车外部视角',
|
title: '指挥车外部视角',
|
||||||
// videoSrc: getVideoUrl('demo/ylzg/单兵视角.mp4'), // 暂时使用单兵视角视频
|
videoSrc: '/videos/vehicle-external-001.mp4',
|
||||||
videoSrc: 'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/单兵视角.mp4',
|
|
||||||
dateRange: '2025/9/1-2025/12/1',
|
dateRange: '2025/9/1-2025/12/1',
|
||||||
hasAudio: true,
|
hasAudio: true,
|
||||||
hasMegaphone: true,
|
hasMegaphone: true,
|
||||||
@ -54,8 +49,7 @@ export const VIDEO_MONITORS = [
|
|||||||
id: 4,
|
id: 4,
|
||||||
type: VIDEO_TYPES.VEHICLE_MEETING,
|
type: VIDEO_TYPES.VEHICLE_MEETING,
|
||||||
title: '指挥车会议视角',
|
title: '指挥车会议视角',
|
||||||
// videoSrc: getVideoUrl('demo/ylzg/无人机视角.mp4'), // 暂时使用无人机视角视频
|
videoSrc: '/videos/vehicle-meeting-001.mp4',
|
||||||
videoSrc: 'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/无人机视角.mp4',
|
|
||||||
dateRange: '2025/9/1-2025/12/1',
|
dateRange: '2025/9/1-2025/12/1',
|
||||||
hasAudio: true,
|
hasAudio: true,
|
||||||
hasMegaphone: true,
|
hasMegaphone: true,
|
||||||
|
|||||||
@ -111,15 +111,11 @@ import { useDisasterData } from "./composables/useDisasterData";
|
|||||||
import { useDualMapCompare } from "./composables/useDualMapCompare";
|
import { useDualMapCompare } from "./composables/useDualMapCompare";
|
||||||
import { useMapMarkers } from "./composables/useMapMarkers";
|
import { useMapMarkers } from "./composables/useMapMarkers";
|
||||||
import { use3DTiles } from "./composables/use3DTiles";
|
import { use3DTiles } from "./composables/use3DTiles";
|
||||||
import { useMapTooltip } from "./composables/useMapTooltip";
|
|
||||||
import { useMapStore } from "@/map";
|
import { useMapStore } from "@/map";
|
||||||
import { request } from "@shared/utils/request";
|
import { request } from "@shared/utils/request";
|
||||||
|
|
||||||
// 标记点图标
|
// 标记点
|
||||||
import emergencyCenterIcon from "./assets/images/应急中心.png";
|
import emergencyCenterIcon from "./assets/images/应急中心.png";
|
||||||
import soldierIcon from "./assets/images/SketchPngfbec927027ff9e49207749ebaafd229429315341fda199251b6dfb1723ff17fb.png";
|
|
||||||
import deviceIcon from "./assets/images/SketchPng860d54f2a31f5f441fc6a88081224f1e98534bf6d5ca1246e420983bdf690380.png";
|
|
||||||
import emergencyBaseIcon from "./assets/images/应急基地.png";
|
|
||||||
|
|
||||||
// 使用灾害数据
|
// 使用灾害数据
|
||||||
const disasterData = useDisasterData();
|
const disasterData = useDisasterData();
|
||||||
@ -154,182 +150,9 @@ const {
|
|||||||
clearEmergencyResourceMarkers,
|
clearEmergencyResourceMarkers,
|
||||||
} = useMapMarkers();
|
} = useMapMarkers();
|
||||||
|
|
||||||
// 地图 Tooltip 功能
|
|
||||||
const { tooltipState: mapTooltip, showTooltip, hideTooltip, updateTooltipPosition } = useMapTooltip();
|
|
||||||
|
|
||||||
// 当前显示 tooltip 的实体(用于相机移动时更新位置)
|
|
||||||
const currentTooltipEntity = ref(null);
|
|
||||||
|
|
||||||
// 3D Tiles加载功能
|
// 3D Tiles加载功能
|
||||||
const { load3DTileset, waitForTilesetReady } = use3DTiles();
|
const { load3DTileset, waitForTilesetReady } = use3DTiles();
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置地图点击事件处理器
|
|
||||||
* 当用户点击地图标记点时,显示 Tooltip
|
|
||||||
*/
|
|
||||||
const setupMapClickHandler = (viewer) => {
|
|
||||||
if (!viewer) return;
|
|
||||||
|
|
||||||
// 创建 ScreenSpaceEventHandler 监听点击事件
|
|
||||||
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
|
|
||||||
|
|
||||||
handler.setInputAction((click) => {
|
|
||||||
// 获取点击位置的实体
|
|
||||||
const pickedObject = viewer.scene.pick(click.position);
|
|
||||||
|
|
||||||
if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
|
|
||||||
const entity = pickedObject.id;
|
|
||||||
|
|
||||||
// 检查实体是否有 properties(标记点才有)
|
|
||||||
if (entity.properties) {
|
|
||||||
const type = entity.properties.type?.getValue();
|
|
||||||
|
|
||||||
// 根据标记类型显示不同的 Tooltip
|
|
||||||
if (type === 'soldier') {
|
|
||||||
showMarkerTooltip(viewer, entity, click.position, soldierIcon);
|
|
||||||
} else if (type === 'device') {
|
|
||||||
showMarkerTooltip(viewer, entity, click.position, deviceIcon);
|
|
||||||
} else if (type === 'emergencyBase' || type === 'station') {
|
|
||||||
showMarkerTooltip(viewer, entity, click.position, emergencyBaseIcon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 点击空白区域,隐藏 Tooltip
|
|
||||||
hideTooltip();
|
|
||||||
currentTooltipEntity.value = null;
|
|
||||||
}
|
|
||||||
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
|
||||||
|
|
||||||
// 监听相机移动事件,更新 tooltip 位置
|
|
||||||
viewer.scene.postRender.addEventListener(() => {
|
|
||||||
if (currentTooltipEntity.value && mapTooltip.value.visible) {
|
|
||||||
updateTooltipPositionForEntity(viewer, currentTooltipEntity.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 显示标记点 Tooltip
|
|
||||||
* @param {Cesium.Viewer} viewer - Cesium viewer 实例
|
|
||||||
* @param {Cesium.Entity} entity - 被点击的实体
|
|
||||||
* @param {Cesium.Cartesian2} screenPosition - 点击的屏幕坐标(备用)
|
|
||||||
* @param {string} icon - 图标路径
|
|
||||||
*/
|
|
||||||
const showMarkerTooltip = (viewer, entity, screenPosition, icon) => {
|
|
||||||
const properties = entity.properties;
|
|
||||||
const type = properties.type?.getValue();
|
|
||||||
|
|
||||||
// 获取实体的 3D 位置
|
|
||||||
const position = entity.position?.getValue(Cesium.JulianDate.now());
|
|
||||||
|
|
||||||
if (!position) {
|
|
||||||
console.warn('[Tooltip] 无法获取实体位置');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对于使用 CLAMP_TO_GROUND 的 billboard,需要获取实际的地形高度
|
|
||||||
const cartographic = Cesium.Cartographic.fromCartesian(position);
|
|
||||||
let clampedPosition = position;
|
|
||||||
|
|
||||||
// 使用 globe.getHeight 获取地形高度
|
|
||||||
if (viewer.scene.globe) {
|
|
||||||
const height = viewer.scene.globe.getHeight(cartographic);
|
|
||||||
if (Cesium.defined(height)) {
|
|
||||||
cartographic.height = height;
|
|
||||||
clampedPosition = Cesium.Cartographic.toCartesian(cartographic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将贴地后的 3D 坐标转换为屏幕坐标
|
|
||||||
const canvasPosition = viewer.scene.cartesianToCanvasCoordinates(clampedPosition);
|
|
||||||
|
|
||||||
if (!Cesium.defined(canvasPosition)) {
|
|
||||||
console.warn('[Tooltip] 无法转换坐标到屏幕位置');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建 Tooltip 数据
|
|
||||||
let title = '';
|
|
||||||
const fields = [];
|
|
||||||
|
|
||||||
if (type === 'soldier') {
|
|
||||||
title = '单兵信息';
|
|
||||||
fields.push(
|
|
||||||
{ label: '姓名', value: properties.name?.getValue() || '-' },
|
|
||||||
{ label: '部门', value: properties.department?.getValue() || '-' },
|
|
||||||
{ label: '位置', value: properties.location?.getValue() || '-' }
|
|
||||||
);
|
|
||||||
} else if (type === 'device') {
|
|
||||||
title = '设备信息';
|
|
||||||
fields.push(
|
|
||||||
{ label: '设备名称', value: properties.name?.getValue() || '-' },
|
|
||||||
{ label: '设备类型', value: properties.deviceType?.getValue() || '-' },
|
|
||||||
{ label: '位置', value: properties.location?.getValue() || '-' }
|
|
||||||
);
|
|
||||||
} else if (type === 'emergencyBase') {
|
|
||||||
title = '应急基地';
|
|
||||||
fields.push(
|
|
||||||
{ label: '名称', value: properties.name?.getValue() || '-' },
|
|
||||||
{ label: '地址', value: properties.address?.getValue() || '-' },
|
|
||||||
{ label: '距离', value: properties.distance?.getValue() || '-' }
|
|
||||||
);
|
|
||||||
} else if (type === 'station') {
|
|
||||||
title = '养护站';
|
|
||||||
fields.push(
|
|
||||||
{ label: '名称', value: properties.name?.getValue() || '-' },
|
|
||||||
{ label: '距离', value: `${properties.distance?.getValue() || 0}公里` }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示 Tooltip,使用实体的屏幕坐标
|
|
||||||
showTooltip({
|
|
||||||
x: canvasPosition.x,
|
|
||||||
y: canvasPosition.y,
|
|
||||||
title,
|
|
||||||
icon,
|
|
||||||
data: { fields }
|
|
||||||
});
|
|
||||||
|
|
||||||
// 保存当前实体,用于相机移动时更新位置
|
|
||||||
currentTooltipEntity.value = entity;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新 Tooltip 位置(当相机移动时)
|
|
||||||
* @param {Cesium.Viewer} viewer - Cesium viewer 实例
|
|
||||||
* @param {Cesium.Entity} entity - 实体对象
|
|
||||||
*/
|
|
||||||
const updateTooltipPositionForEntity = (viewer, entity) => {
|
|
||||||
const position = entity.position?.getValue(Cesium.JulianDate.now());
|
|
||||||
|
|
||||||
if (!position) return;
|
|
||||||
|
|
||||||
// 对于使用 CLAMP_TO_GROUND 的 billboard,需要获取实际的地形高度
|
|
||||||
const cartographic = Cesium.Cartographic.fromCartesian(position);
|
|
||||||
let clampedPosition = position;
|
|
||||||
|
|
||||||
// 使用 globe.getHeight 获取地形高度
|
|
||||||
if (viewer.scene.globe) {
|
|
||||||
const height = viewer.scene.globe.getHeight(cartographic);
|
|
||||||
if (Cesium.defined(height)) {
|
|
||||||
cartographic.height = height;
|
|
||||||
clampedPosition = Cesium.Cartographic.toCartesian(cartographic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将贴地后的 3D 坐标转换为屏幕坐标
|
|
||||||
const canvasPosition = viewer.scene.cartesianToCanvasCoordinates(clampedPosition);
|
|
||||||
|
|
||||||
// 如果标记点在视野外,隐藏 tooltip
|
|
||||||
if (!Cesium.defined(canvasPosition)) {
|
|
||||||
hideTooltip();
|
|
||||||
currentTooltipEntity.value = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateTooltipPosition(canvasPosition.x, canvasPosition.y);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 初始化地图
|
// 初始化地图
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 等待地图就绪后配置初始视图和模型对比图层
|
// 等待地图就绪后配置初始视图和模型对比图层
|
||||||
@ -374,10 +197,6 @@ onMounted(() => {
|
|||||||
...DEFAULT_CAMERA_VIEW,
|
...DEFAULT_CAMERA_VIEW,
|
||||||
duration: 1,
|
duration: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 设置地图点击事件监听 - 显示 Tooltip
|
|
||||||
setupMapClickHandler(viewer);
|
|
||||||
|
|
||||||
// 延迟 1000ms 后设置相机到默认位置
|
// 延迟 1000ms 后设置相机到默认位置
|
||||||
// setTimeout(() => {
|
// setTimeout(() => {
|
||||||
// camera.flyTo({
|
// camera.flyTo({
|
||||||
@ -385,7 +204,7 @@ onMounted(() => {
|
|||||||
// duration: 1,
|
// duration: 1,
|
||||||
// });
|
// });
|
||||||
// }, 5000);
|
// }, 5000);
|
||||||
// return;
|
return;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置相机到指定的笛卡尔坐标
|
* 设置相机到指定的笛卡尔坐标
|
||||||
@ -446,7 +265,7 @@ onMounted(() => {
|
|||||||
console.log("[index.vue] 开始初始化地图标记...");
|
console.log("[index.vue] 开始初始化地图标记...");
|
||||||
const sampledCollapseCenter = await initializeMarkers(viewer, {
|
const sampledCollapseCenter = await initializeMarkers(viewer, {
|
||||||
useSampledHeights: true, // 使用采样高度,确保标记位置准确
|
useSampledHeights: true, // 使用采样高度,确保标记位置准确
|
||||||
heightOffset: 100, // 标记相对地面100米(与 WuRenJi 保持一致)
|
heightOffset: 10, // 标记相对地面10米
|
||||||
});
|
});
|
||||||
|
|
||||||
// 如果之前没有设置相机(配置数据缺失),现在再次尝试
|
// 如果之前没有设置相机(配置数据缺失),现在再次尝试
|
||||||
@ -590,6 +409,20 @@ const selectedCenter = ref({
|
|||||||
image: null,
|
image: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地图 Tooltip 状态管理
|
||||||
|
* 用于显示地图标记点的轻量级信息提示框
|
||||||
|
*/
|
||||||
|
const mapTooltip = ref({
|
||||||
|
visible: false,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
title: "",
|
||||||
|
icon: "",
|
||||||
|
zIndex: 20, // 高于地图控件层,低于全屏弹窗
|
||||||
|
data: null, // 业务数据,用于内容插槽渲染
|
||||||
|
});
|
||||||
|
|
||||||
// 返回驾驶舱
|
// 返回驾驶舱
|
||||||
const handleBack = () => {
|
const handleBack = () => {
|
||||||
console.log("返回驾驶舱");
|
console.log("返回驾驶舱");
|
||||||
|
|||||||
@ -16,31 +16,3 @@ export const APP_CONFIG = {
|
|||||||
title: '数据大屏',
|
title: '数据大屏',
|
||||||
version: '1.0.0'
|
version: '1.0.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
// OSS 配置
|
|
||||||
// 注意: 实际使用时需要从配置中心或环境变量读取,此处为示例配置
|
|
||||||
export const OSS_CONFIG = {
|
|
||||||
// http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/%E5%8D%95%E5%85%B5%E8%A7%86%E8%A7%92.mp4
|
|
||||||
// OSS 服务地址
|
|
||||||
url: import.meta.env.VITE_OSS_URL || 'http://222.212.85.86:9000',
|
|
||||||
// OSS bucket
|
|
||||||
bucket: import.meta.env.VITE_OSS_BUCKET || '300bdf2b-a150-406e-be63-d28bd29b409f'
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取 OSS 配置
|
|
||||||
* @returns {{url: string, bucket: string}}
|
|
||||||
*/
|
|
||||||
export const getOssConfig = () => {
|
|
||||||
const { url, bucket } = OSS_CONFIG
|
|
||||||
|
|
||||||
// 确保 URL 包含协议
|
|
||||||
if (url.includes('http://') || url.includes('https://')) {
|
|
||||||
return { url, bucket }
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
url: `http://${url}`,
|
|
||||||
bucket
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import { getOssConfig } from '../config'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 格式化日期
|
* 格式化日期
|
||||||
* @param {Date|string|number} date
|
* @param {Date|string|number} date
|
||||||
@ -75,34 +73,3 @@ export function deepClone(obj) {
|
|||||||
}
|
}
|
||||||
return clonedObj
|
return clonedObj
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取 OSS 资源 URL
|
|
||||||
* @param {string} path - OSS 对象路径,如 'demo/ylzg/单兵视角.mp4'
|
|
||||||
* @returns {string} 完整的 OSS 资源 URL
|
|
||||||
* @example
|
|
||||||
* getAssetUrl('demo/ylzg/单兵视角.mp4')
|
|
||||||
* // => 'http://183.221.225.106:9001/6251daf8-4127-40e0-980d-c86f8a765b20/demo/ylzg/单兵视角.mp4'
|
|
||||||
*/
|
|
||||||
export function getAssetUrl(path) {
|
|
||||||
const { url, bucket } = getOssConfig()
|
|
||||||
return `${url}/${bucket}/${path}`
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取视频 URL (getAssetUrl 的别名,用于语义化)
|
|
||||||
* @param {string} path - 视频文件路径
|
|
||||||
* @returns {string} 完整的视频 URL
|
|
||||||
*/
|
|
||||||
export function getVideoUrl(path) {
|
|
||||||
return getAssetUrl(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取图片 URL (getAssetUrl 的别名,用于语义化)
|
|
||||||
* @param {string} path - 图片文件路径
|
|
||||||
* @returns {string} 完整的图片 URL
|
|
||||||
*/
|
|
||||||
export function getImageUrl(path) {
|
|
||||||
return getAssetUrl(path)
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user