DiKongGanZhiPingTai/src/views/demo/system/mediaLibrary/preview/Map.vue

469 lines
14 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div ref="vChartRef" id="mars3d-container" class="mars3d-container">
<div class="mapInfo">
<span> {{ props.nowPreviewRecord.lat }}°N</span>
<span> {{ props.nowPreviewRecord.lng }}°E</span>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, watch, onMounted, defineEmits } from 'vue';
import * as mars3d from 'mars3d';
import * as Cesium from 'mars3d-cesium';
import { getAppEnvConfig } from '@/utils/env';
const { VITE_MEDIALIBRARY_IMAGE_URL } = getAppEnvConfig();
const props = defineProps(['nowPreviewRecord', 'previewRecordList', 'hideOrShowTextboxFlag']);
const emits = defineEmits(['chooseNowPreviewRecord']);
let map: mars3d.Map; // 地图对象
let graphicLayers = new mars3d.layer.GraphicLayer();
// 地图照片-地面点到展示图片的线
let bottomImagePolylineGraphicData: any = [];
// 地图照片-展示图片
let imageGraphicData: any = [];
const vChartRef: any = ref<HTMLElement>();
onMounted(() => {
initMap();
});
// 显示or隐藏地图上的其他标注信息
watch(
() => props.hideOrShowTextboxFlag,
(newValue) => {
imageGraphicData.forEach((graphic) => {
if (graphic.options.id !== props.nowPreviewRecord.id) {
graphic.setStyle({
show: newValue,
});
}
});
bottomImagePolylineGraphicData.forEach((graphic) => {
if (graphic.options.id !== props.nowPreviewRecord.id + '_polyline') {
graphic.setStyle({
show: newValue,
});
}
});
},
);
// 显示or隐藏地图上的其他标注信息
watch(
() => props.nowPreviewRecord,
() => {
imageGraphicData.forEach((graphic) => {
if (graphic.options.id !== props.nowPreviewRecord.id) {
graphic.setStyle({
image: graphic.options.defaultImage,
show: props.hideOrShowTextboxFlag,
});
} else {
graphic.setStyle({
image: graphic.options.chooseImage,
show: true,
});
}
});
bottomImagePolylineGraphicData.forEach((graphic) => {
if (graphic.options.id !== props.nowPreviewRecord.id + '_polyline') {
graphic.setStyle({
show: props.hideOrShowTextboxFlag,
});
} else {
graphic.setStyle({
show: true,
});
}
});
},
);
const initMap = () => {
map = new mars3d.Map(vChartRef.value, {
scene: {
center: {
lat: parseFloat(props.nowPreviewRecord.lat),
lng: parseFloat(props.nowPreviewRecord.lng),
alt: 8306.3,
heading: 360,
pitch: -45,
},
scene3DOnly: false,
shadows: false,
removeDblClick: true,
sceneMode: 3,
showSun: true,
showMoon: true,
showSkyBox: true,
showSkyAtmosphere: true,
fog: true,
fxaa: true,
requestRenderMode: true,
contextOptions: {
requestWebgl1: false,
webgl: {
preserveDrawingBuffer: true,
alpha: false,
stencil: true,
powerPreference: 'high-performance',
},
},
globe: {
depthTestAgainstTerrain: false,
baseColor: '#546a53',
showGroundAtmosphere: true,
enableLighting: false,
},
cameraController: {
zoomFactor: 3,
minimumZoomDistance: 1,
maximumZoomDistance: 50000000,
enableRotate: true,
enableTranslate: true,
enableTilt: true,
enableZoom: true,
enableCollisionDetection: true,
minimumCollisionTerrainHeight: 15000,
},
},
control: {
homeButton: true,
baseLayerPicker: false,
sceneModePicker: false,
vrButton: false,
fullscreenButton: false,
navigationHelpButton: false,
animation: false,
timeline: false,
infoBox: false,
geocoder: false,
selectionIndicator: false,
showRenderLoopErrors: false,
contextmenu: {
hasDefault: false,
},
mouseDownView: false,
zoom: false,
compass: false,
distanceLegend: false,
},
method: {
templateValues: {
dataServer: '//data.mars3d.cn',
gltfServerUrl: '//data.mars3d.cn/gltf',
},
},
terrain: {
url: '//data.mars3d.cn/terrain',
show: true,
clip: true,
},
basemaps: [
{
id: 10,
name: '地图底图',
type: 'group',
opacity: 1,
},
{
id: 2021,
pid: 10,
name: '天地图影像',
icon: 'https://data.mars3d.cn/img/thumbnail/basemap/tdt_img.png',
type: 'group',
layers: [
{
name: '底图',
type: 'tdt',
layer: 'img_d',
eventParent: {
id: 2021,
pid: 10,
name: '天地图影像',
icon: 'https://data.mars3d.cn/img/thumbnail/basemap/tdt_img.png',
type: 'group',
layers: [
{
name: '底图',
type: 'tdt',
layer: 'img_d',
show: true,
},
{
name: '注记',
type: 'tdt',
layer: 'img_z',
show: true,
},
],
show: true,
},
private: false,
id: 'm-770c35e7-9054-4259-b5ee-c15f108becd0',
opacity: 1,
pid: 2021,
parent: {
id: 2021,
pid: 10,
name: '天地图影像',
icon: 'https://data.mars3d.cn/img/thumbnail/basemap/tdt_img.png',
type: 'group',
layers: [
{
name: '底图',
type: 'tdt',
layer: 'img_d',
show: true,
},
{
name: '注记',
type: 'tdt',
layer: 'img_z',
show: true,
},
],
show: true,
},
zIndex: 1,
},
{
name: '注记',
type: 'tdt',
layer: 'img_z',
eventParent: {
id: 2021,
pid: 10,
name: '天地图影像',
icon: 'https://data.mars3d.cn/img/thumbnail/basemap/tdt_img.png',
type: 'group',
layers: [
{
name: '底图',
type: 'tdt',
layer: 'img_d',
show: true,
},
{
name: '注记',
type: 'tdt',
layer: 'img_z',
show: true,
},
],
show: true,
},
private: false,
id: 'm-3b881368-574b-48a5-88b2-8b3c2c48fd62',
opacity: 1,
pid: 2021,
parent: {
id: 2021,
pid: 10,
name: '天地图影像',
icon: 'https://data.mars3d.cn/img/thumbnail/basemap/tdt_img.png',
type: 'group',
layers: [
{
name: '底图',
type: 'tdt',
layer: 'img_d',
show: true,
},
{
name: '注记',
type: 'tdt',
layer: 'img_z',
show: true,
},
],
show: true,
},
zIndex: 2,
},
],
show: true,
opacity: 1,
},
],
layers: [],
});
if (map) {
map.addLayer(graphicLayers);
// 图层
showAllImageDataList();
const position = Cesium.Cartesian3.fromDegrees(
parseFloat(props.nowPreviewRecord.lng),
parseFloat(props.nowPreviewRecord.lat),
);
map.flyToPoint(position);
}
};
// 地图照片-初始化-遍历展示
const showAllImageDataList = async () => {
// 删除旧数据
imageGraphicData?.forEach((graphicLayer) => {
graphicLayers.removeGraphic(graphicLayer);
});
bottomImagePolylineGraphicData?.forEach((graphicLayer) => {
graphicLayers.removeGraphic(graphicLayer);
});
// 图层数据
imageGraphicData = [];
bottomImagePolylineGraphicData = [];
props.previewRecordList.forEach((item, index) => {
if (item.lng && item.lat && item.absoluteAltitude) {
const image = new Image();
image.crossOrigin = 'Anonymous';
// if (item.minipic) {
// image.src = VITE_MEDIALIBRARY_IMAGE_URL + item.minipic;
// } else {
image.src =
'https://m.tuniucdn.com/fb2/t1/G5/M00/44/52/Cii-s1soezyIF2UxABn76u-yKl8AAIwBgB34jAAGfwC3020871';
// }
image.onload = () => {
// 创建Canvas元素
const canvas = document.createElement('canvas');
canvas.width = 30;
canvas.height = 30;
// 获取Canvas绘图上下文
const ctx = canvas.getContext('2d');
// 绘制一个圆形裁剪区域
ctx.beginPath();
ctx.arc(15, 15, 20, 0, Math.PI * 2, true);
ctx.closePath();
ctx.clip(); // 裁剪区域
ctx.fillStyle = '#ffffff00';
ctx?.fillRect(0, 0, canvas.width, canvas.height);
// 在Canvas上绘制图片
ctx.drawImage(image, 2, 2, 26, 26);
// 设置边框颜色和宽度
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = 2;
ctx.strokeRect(1, 1, canvas.width - 2, canvas.height - 2);
// 将Canvas内容转换为图片的数据URL
const dataURL1 = canvas.toDataURL('image/png');
// 在Canvas上绘制图片假设image变量已经定义并且是一个有效的Image对象
ctx.drawImage(image, 2, 2, 26, 26);
// 设置边框颜色和宽度
ctx.strokeStyle = '#2d8cef'; // 蓝色边框
ctx.lineWidth = 2; // 边框宽度
// 绘制边框
ctx.strokeRect(1, 1, canvas.width - 2, canvas.height - 2); // 调整坐标和尺寸以适应边框宽度
// 将Canvas内容转换为图片的数据URL
const dataURL2 = canvas.toDataURL('image/png');
// 位置
let position = [
parseFloat(item.lng),
parseFloat(item.lat),
parseFloat(item.absoluteAltitude),
];
// 地形高度
mars3d.PointUtil.getSurfaceHeight(
map.scene,
Cesium.Cartesian3.fromDegrees(position[0], position[1]),
).then((point) => {
// 地面点到展示图片的线
let bottomImagePolylineGraphic = new mars3d.graphic.PolylineEntity({
id: item.id + '_polyline',
positions: [
Cesium.Cartesian3.fromDegrees(position[0], position[1], point.height),
Cesium.Cartesian3.fromDegrees(position[0], position[1], position[2]),
],
style: {
color: '#ffffff',
width: 1, // 线宽
clampToGround: false,
},
hasEdit: false,
});
// 展示图片
let imageGraphic = new mars3d.graphic.BillboardEntity({
id: item.id,
position: [position[0], position[1], position[2]],
style: {
image: item.id == props.nowPreviewRecord.id ? dataURL2 : dataURL1,
clampToGround: false,
scale: 1,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
},
hasEdit: false,
// 用于恢复默认
defaultImage: dataURL1,
// 用于外侧修改图片
chooseImage: dataURL2,
});
// 监听点击事件
imageGraphic.on(mars3d.EventType.click, function () {
if (props.nowPreviewRecord.id !== item.id) {
clickSetImage(item);
}
});
// 添加到图层中
graphicLayers.addGraphic(bottomImagePolylineGraphic);
graphicLayers.addGraphic(imageGraphic);
// 数据
bottomImagePolylineGraphicData.push(bottomImagePolylineGraphic);
imageGraphicData.push(imageGraphic);
});
};
}
});
};
// 点击事件
function clickSetImage(item) {
imageGraphicData.forEach((graphic) => {
if (graphic.options.id == item.id) {
graphic.setStyle({
image: graphic.options.chooseImage,
});
emits('chooseNowPreviewRecord', item);
} else {
graphic.setStyle({
image: graphic.options.defaultImage,
});
}
});
}
</script>
<style lang="less" scoped>
.mars3d-container {
position: relative;
width: 100%;
height: 100%;
}
.mapInfo {
position: absolute;
width: 100%;
height: 30px;
bottom: 0px;
left: 0px;
background: #3d3f3aaa;
z-index: 1000;
display: flex;
justify-content: flex-start;
span {
height: 100%;
width: 30%;
color: #ffffff;
display: flex;
align-items: center;
justify-content: flex-start;
font-size: 15px;
margin-left: 10px;
}
}
</style>