You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1272 lines
40 KiB
Vue

<template>
<!-- <div class="map-out-container"> -->
<!-- <div class="map-inner-container"> -->
<div ref="vChartRef" id="mars3d-container" class="mars3d-container">
<div class="annotationButtons">
<div
:class="mapDrawType == 'drawPoint' ? 'button_choose' : 'button_nochoose'"
@click="drawPoint"
>
<a-popover placement="left">
<template #content>
<div style="display: flex; gap: 5px">
<div
class="popoverAnnotation"
v-for="color in ['#2D8CF0', '#19BE6B', '#FFBB00', '#E23C39', '#B620E0']"
:key="color"
:style="{ background: color }"
@click="drawColorPoint = color"
>
<CheckOutlined v-if="drawColorPoint == color" style="color: white" />
</div>
</div>
</template>
<AntDesignOutlined
:style="{
color: drawColorPoint,
fontSize: '20px',
}"
/>
</a-popover>
</div>
<div
:class="mapDrawType == 'drawPolyline' ? 'button_choose' : 'button_nochoose'"
@click="drawPolyline"
>
<a-popover placement="left">
<template #content>
<div style="display: flex; gap: 5px">
<div
class="popoverAnnotation"
v-for="color in ['#2D8CF0', '#19BE6B', '#FFBB00', '#E23C39', '#B620E0']"
:key="color"
:style="{ background: color }"
@click="drawColorPolyline = color"
>
<CheckOutlined v-if="drawColorPolyline == color" style="color: white" />
</div>
</div>
</template>
<ExpandAltOutlined
:style="{
color: drawColorPolyline,
fontSize: '20px',
}"
/>
</a-popover>
</div>
<div
:class="mapDrawType == 'drawPolygon' ? 'button_choose' : 'button_nochoose'"
@click="drawPolygon"
>
<a-popover placement="left">
<template #content>
<div style="display: flex; gap: 5px">
<div
class="popoverAnnotation"
v-for="color in ['#2D8CF0', '#19BE6B', '#FFBB00', '#E23C39', '#B620E0']"
:key="color"
:style="{ background: color }"
@click="drawColorPolygon = color"
>
<CheckOutlined v-if="drawColorPolygon == color" style="color: white" />
</div>
</div>
</template>
<BorderOutlined
:style="{
color: drawColorPolygon,
fontSize: '20px',
}"
/>
</a-popover>
</div>
<div
:class="mapDrawType == 'drawCricle' ? 'button_choose' : 'button_nochoose'"
@click="drawCricle"
>
<a-popover placement="left">
<template #content>
<div style="display: flex; gap: 5px">
<div
class="popoverAnnotation"
v-for="color in ['#2D8CF0', '#19BE6B', '#FFBB00', '#E23C39', '#B620E0']"
:key="color"
:style="{ background: color }"
@click="drawColorCricle = color"
>
<CheckOutlined v-if="drawColorCricle == color" style="color: white" />
</div>
</div>
</template>
<LogoutOutlined
:style="{
color: drawColorCricle,
fontSize: '20px',
}"
/>
</a-popover>
</div>
</div>
<!-- </div> -->
<!-- </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 { circle, rect, triangle } from './svg';
import {
CheckOutlined,
AntDesignOutlined,
ExpandAltOutlined,
BorderOutlined,
LogoutOutlined,
} from '@ant-design/icons-vue';
import { AddAnnotation, UpdateAnnotation } from '@/api/demo/mediaLibrary';
import {
locateBack,
defaultIcon,
fireIcon,
peopleIcon,
warnIcon,
carIcon,
checkIcon,
closeIcon,
} from './svg';
import * as turf from '@turf/turf';
import { GeojsonToWkt } from '@/components/MapboxMaps/src/WktGeojsonTransform';
import dayjs from 'dayjs';
const props = defineProps(['allAnnotationDataList', 'nowShowAnnotationData']);
const emits = defineEmits(['setNowShowAnnotationData', 'setAllAnnotationData']);
const vChartRef: any = ref<HTMLElement>();
let map: mars3d.Map; // 地图对象
let graphicLayers = new mars3d.layer.GraphicLayer({
isAutoEditing: true,
});
// 地图标注
// 地图标注-点
let annotation_PointGraphicData: any = [];
// 地图标注-线
let annotation_LineStringGraphicData: any = [];
// 地图标注-多边形
let annotation_PolygonGraphicData: any = [];
// 地图标注-圈
let annotation_CircleGraphicData: any = [];
onMounted(() => {
initMap();
});
const initMap = () => {
map = new mars3d.Map(vChartRef.value, {
scene: {
center: {
lat: 35.134608,
lng: 118.29853,
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: true,
vrButton: false,
fullscreenButton: true,
navigationHelpButton: true,
animation: false,
timeline: false,
infoBox: false,
geocoder: false,
selectionIndicator: false,
showRenderLoopErrors: true,
contextmenu: {
hasDefault: true,
},
mouseDownView: true,
zoom: {
insertIndex: 1,
},
compass: {
bottom: 'toolbar',
left: '5px',
rotation: true,
},
distanceLegend: {
left: '10px',
bottom: '2px',
},
locationBar: {
crs: 'CGCS2000_GK_Zone_3',
crsDecimal: 0,
template:
"<div>经度:{lng}</div> <div>纬度:{lat}</div> <div class='hide1000'>横{crsx} 纵{crsy}</div> <div>海拔:{alt}米</div> <div class='hide700'>层级:{level}</div><div>方向:{heading}°</div> <div>俯仰角:{pitch}°</div><div class='hide700'>视高:{cameraHeight}米</div>",
cacheTime: 50,
},
},
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);
// 图层
showAllAnnotationDataList();
handlerLocation([118.2958779, 35.1342553]);
// 监听地图点击事件
map.on(mars3d.EventType.click, function (event) {
if (!event.czmObject) {
// 地图标注 - 恢复默认
// if (props.nowShowAnnotationData && props.nowShowAnnotationData.id) {
// annotationRestoreDefault();
// emits('setNowShowAnnotationData', {});
// }
}
});
}
};
// 地图标注--------------------------------------------------------------------
watch(
() => props.allAnnotationDataList,
() => {
showAllAnnotationDataList();
},
);
watch(
() => props.nowShowAnnotationData,
(newVal, oldVal) => {
let time = dayjs().format('YYYY-MM-DD HH:mm:ss');
if (newVal) {
// 点
annotation_PointGraphicData?.forEach((graphicLayer) => {
if (graphicLayer.options.id == props.nowShowAnnotationData.id) {
const image1 = new Image();
image1.crossOrigin = 'Anonymous';
image1.src = svgToDataURL(
locateBack.replaceAll('currentColor', props.nowShowAnnotationData.properties.color),
);
image1.onload = () => {
const image2 = new Image();
image2.crossOrigin = 'Anonymous';
let svgString = '';
switch (props.nowShowAnnotationData.properties.iconname) {
case 'defaultIcon':
svgString = defaultIcon;
break;
case 'fireIcon':
svgString = fireIcon;
break;
case 'peopleIcon':
svgString = peopleIcon;
break;
case 'warnIcon':
svgString = warnIcon;
break;
case 'carIcon':
svgString = carIcon;
break;
case 'checkIcon':
svgString = checkIcon;
break;
case 'closeIcon':
svgString = closeIcon;
break;
}
image2.src = svgToDataURL(
svgString.replaceAll('currentColor', props.nowShowAnnotationData.properties.color),
);
image2.onload = () => {
// 创建Canvas元素
const canvas = document.createElement('canvas');
canvas.width = 30;
canvas.height = 40;
// 获取Canvas绘图上下文
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#00000000';
ctx?.fillRect(0, 0, canvas.width, canvas.height);
// 在Canvas上绘制图片
if (props.nowShowAnnotationData.properties.iconname == 'defaultIcon') {
ctx.drawImage(image2, 0, 0, canvas.width, canvas.height);
} else {
ctx.drawImage(image1, 0, 0, canvas.width, canvas.height);
ctx.drawImage(image2, 8, 3, 14, 28);
}
// 将Canvas内容转换为图片的数据URL
const dataURL2 = canvas.toDataURL('image/png');
graphicLayer.position = [
parseFloat(props.nowShowAnnotationData.coordinates[0]),
parseFloat(props.nowShowAnnotationData.coordinates[1]),
parseFloat(props.nowShowAnnotationData.coordinates[2]),
];
graphicLayer.setStyle({
// 图标(待修改)
image: dataURL2,
iconname: props.nowShowAnnotationData.properties.iconname,
label: {
text: props.nowShowAnnotationData.name,
color: props.nowShowAnnotationData.properties.color,
font_size: props.nowShowAnnotationData.properties.font_size,
},
});
if (oldVal && newVal.id == oldVal.id) {
addAndUpdateWorkAnnotation(graphicLayer, 'point', time, 'update');
}
};
};
}
});
// 线
annotation_LineStringGraphicData?.forEach((graphicLayer) => {
if (graphicLayer.options.id == props.nowShowAnnotationData.id) {
graphicLayer.setStyle({
// 线头部样式/线尾部样式(待修改)
width: props.nowShowAnnotationData.properties.line_width,
color: props.nowShowAnnotationData.properties.color,
label: {
text: props.nowShowAnnotationData.name,
color: props.nowShowAnnotationData.properties.color,
font_size: props.nowShowAnnotationData.properties.font_size,
},
});
if (oldVal && newVal.id == oldVal.id) {
addAndUpdateWorkAnnotation(graphicLayer, 'polyline', time, 'update');
}
}
});
// 多边形
annotation_PolygonGraphicData?.forEach((graphicLayer) => {
if (graphicLayer.options.id == props.nowShowAnnotationData.id) {
graphicLayer.setStyle({
outlineColor: props.nowShowAnnotationData.properties.color,
label: {
text: props.nowShowAnnotationData.name,
color: props.nowShowAnnotationData.properties.color,
font_size: props.nowShowAnnotationData.properties.font_size,
},
});
if (oldVal && newVal.id == oldVal.id) {
addAndUpdateWorkAnnotation(graphicLayer, 'polygon', time, 'update');
}
}
});
// 圆
annotation_CircleGraphicData?.forEach((graphicLayer) => {
if (graphicLayer.options.id == props.nowShowAnnotationData.id) {
graphicLayer.position = [
parseFloat(props.nowShowAnnotationData.properties.centerPoint[0]),
parseFloat(props.nowShowAnnotationData.properties.centerPoint[1]),
parseFloat(props.nowShowAnnotationData.properties.centerPoint[2]),
];
graphicLayer.setStyle({
radius: props.nowShowAnnotationData.properties.radius,
outlineColor: props.nowShowAnnotationData.properties.color,
label: {
text: props.nowShowAnnotationData.name,
color: props.nowShowAnnotationData.properties.color,
font_size: props.nowShowAnnotationData.properties.font_size,
},
});
if (oldVal && newVal.id == oldVal.id) {
addAndUpdateWorkAnnotation(graphicLayer, 'circle', time, 'update');
}
}
});
}
},
{
deep: true,
},
);
// 地图标注-初始化-遍历展示
const showAllAnnotationDataList = async () => {
// 删除旧数据
annotation_PointGraphicData?.forEach((graphicLayer) => {
graphicLayers.removeGraphic(graphicLayer);
});
annotation_LineStringGraphicData?.forEach((graphicLayer) => {
graphicLayers.removeGraphic(graphicLayer);
});
annotation_PolygonGraphicData?.forEach((graphicLayer) => {
graphicLayers.removeGraphic(graphicLayer);
});
annotation_CircleGraphicData?.forEach((graphicLayer) => {
graphicLayers.removeGraphic(graphicLayer);
});
// 图层数据
annotation_PointGraphicData = [];
annotation_LineStringGraphicData = [];
annotation_PolygonGraphicData = [];
annotation_CircleGraphicData = [];
if (!props.allAnnotationDataList || props.allAnnotationDataList.length == 0) {
return;
}
// 地图标注-遍历
props.allAnnotationDataList.forEach((item, index) => {
// console.log(item);
// 地图标注-点
if (item.type == 0) {
const image1 = new Image();
image1.crossOrigin = 'Anonymous';
image1.src = svgToDataURL(locateBack.replaceAll('currentColor', item.properties.color));
image1.onload = () => {
const image2 = new Image();
image2.crossOrigin = 'Anonymous';
let svgString = '';
switch (item.properties.iconname) {
case 'defaultIcon':
svgString = defaultIcon;
break;
case 'fireIcon':
svgString = fireIcon;
break;
case 'warnIcon':
svgString = warnIcon;
break;
case 'peopleIcon':
svgString = peopleIcon;
break;
case 'carIcon':
svgString = carIcon;
break;
case 'checkIcon':
svgString = checkIcon;
break;
case 'closeIcon':
svgString = closeIcon;
break;
}
image2.src = svgToDataURL(svgString.replaceAll('currentColor', item.properties.color));
image2.onload = () => {
// 创建Canvas元素
const canvas = document.createElement('canvas');
canvas.width = 30;
canvas.height = 40;
// 获取Canvas绘图上下文
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#00000000';
ctx?.fillRect(0, 0, canvas.width, canvas.height);
// 在Canvas上绘制图片
if (item.properties.iconname == 'defaultIcon') {
ctx.drawImage(image2, 0, 0, canvas.width, canvas.height);
} else {
ctx.drawImage(image1, 0, 0, canvas.width, canvas.height);
ctx.drawImage(image2, 8, 3, 14, 28);
}
// 将Canvas内容转换为图片的数据URL
const dataURL = canvas.toDataURL('image/png');
let pointGraphic = new mars3d.graphic.BillboardEntity({
id: item.id,
position: item.coordinates,
style: {
image: dataURL,
iconname: item.properties.iconname,
clampToGround: item.properties.clampToGround,
scale: 1,
verticalOrigin: Cesium.VerticalOrigin.CENTER,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
label: {
text: `${item.name}`,
font_size: item.properties.font_size,
color: '#000000',
outline: true,
outlineColor: '#ffffff',
outlineWidth: 6,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
pixelOffset: [25, 0],
},
},
show: item.state == 0 ? true : false,
hasEdit: true,
});
// 监听mouseover事件
pointGraphic.on(mars3d.EventType.mouseOver, function () {
if (!props.nowShowAnnotationData || props.nowShowAnnotationData.id !== item.id) {
pointGraphic.setStyle({
label: {
color: item.properties.color,
},
});
}
});
// 监听mouseout事件
pointGraphic.on(mars3d.EventType.mouseOut, function () {
if (!props.nowShowAnnotationData || props.nowShowAnnotationData.id !== item.id) {
pointGraphic.setStyle({
label: {
color: '#000000',
},
});
}
});
// 监听点击事件
pointGraphic.on(mars3d.EventType.click, function () {
// 全部恢复默认
annotationRestoreDefault();
pointGraphic.setStyle({
label: {
color: item.properties.color,
},
});
emits('setNowShowAnnotationData', item);
});
// 将点对象 添加到图层中
graphicLayers.addGraphic(pointGraphic);
// 数据
annotation_PointGraphicData.push(pointGraphic);
};
};
}
// 地图标注-线
if (item.type == 1) {
let lineGraphic = new mars3d.graphic.PolylineEntity({
id: item.id,
positions: item.coordinates,
style: {
color: item.properties.color,
width: item.properties.line_width,
label: {
text: `${item.name}`,
font_size: item.properties.font_size,
color: '#000000',
outline: true,
outlineColor: '#ffffff',
outlineWidth: 6,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
pixelOffset: [25, -5],
},
},
show: item.state == 0 ? true : false,
hasEdit: true,
drawShowMeasure: true,
});
// 监听mouseover事件
lineGraphic.on(mars3d.EventType.mouseOver, function () {
if (!props.nowShowAnnotationData || props.nowShowAnnotationData.id !== item.id) {
lineGraphic.setStyle({
label: {
color: item.properties.color,
},
});
}
});
// 监听mouseout事件
lineGraphic.on(mars3d.EventType.mouseOut, function () {
if (!props.nowShowAnnotationData || props.nowShowAnnotationData.id !== item.id) {
lineGraphic.setStyle({
label: {
color: '#000000',
},
});
}
});
// 监听点击事件
lineGraphic.on(mars3d.EventType.click, function () {
// 全部恢复默认
annotationRestoreDefault();
lineGraphic.setStyle({
label: {
color: item.properties.color,
},
});
emits('setNowShowAnnotationData', item);
});
// 将线对象 添加到图层中
graphicLayers.addGraphic(lineGraphic);
// 数据
annotation_LineStringGraphicData.push(lineGraphic);
}
// 地图标注-多边形
if (item.type == 2) {
let polygonGraphic = new mars3d.graphic.PolygonEntity({
id: item.id,
positions: item.coordinates,
style: {
color: item.properties.color,
fill: false,
width: item.properties.line_width,
outlineColor: item.properties.color,
outlineWidth: 2,
outline: true,
clampToGround: item.properties.clampToGround,
label: {
text: `${item.name}`,
font_size: item.properties.font_size,
color: '#000000',
outline: true,
outlineColor: '#ffffff',
outlineWidth: 6,
verticalOrigin: Cesium.VerticalOrigin.CENTER,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
},
},
show: item.state == 0 ? true : false,
hasEdit: true,
drawShowMeasure: true,
});
// 监听mouseover事件
polygonGraphic.on(mars3d.EventType.mouseOver, function () {
if (!props.nowShowAnnotationData || props.nowShowAnnotationData.id !== item.id) {
polygonGraphic.setStyle({
// color: '#ffffff00',
label: {
color: item.properties.color,
},
});
}
});
// 监听mouseout事件
polygonGraphic.on(mars3d.EventType.mouseOut, function () {
if (!props.nowShowAnnotationData || props.nowShowAnnotationData.id !== item.id) {
polygonGraphic.setStyle({
label: {
color: '#000000',
},
});
}
});
// 监听点击事件
polygonGraphic.on(mars3d.EventType.click, function () {
// 全部恢复默认
annotationRestoreDefault();
polygonGraphic.setStyle({
label: {
color: item.properties.color,
},
});
emits('setNowShowAnnotationData', item);
});
// 将形状对象 添加到图层中
graphicLayers.addGraphic(polygonGraphic);
// 数据
annotation_PolygonGraphicData.push(polygonGraphic);
}
// 地图标注-圆
if (item.type == 3) {
let circleGraphic = new mars3d.graphic.CircleEntity({
id: item.id,
position: item.properties.centerPoint,
style: {
radius: item.properties.radius,
fill: false,
outlineColor: item.properties.color,
outlineWidth: 4,
outline: true,
clampToGround: item.properties.clampToGround,
label: {
text: `${item.name}`,
font_size: item.properties.font_size,
color: '#000000',
outline: true,
outlineColor: '#ffffff',
outlineWidth: 6,
verticalOrigin: Cesium.VerticalOrigin.CENTER,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
},
},
show: item.state == 0 ? true : false,
hasEdit: true,
drawShowMeasure: true,
});
// 监听mouseover事件
circleGraphic.on(mars3d.EventType.mouseOver, function () {
if (!props.nowShowAnnotationData || props.nowShowAnnotationData.id !== item.id) {
circleGraphic.setStyle({
label: {
color: item.properties.color,
},
});
}
});
// 监听mouseout事件
circleGraphic.on(mars3d.EventType.mouseOut, function () {
if (!props.nowShowAnnotationData || props.nowShowAnnotationData.id !== item.id) {
circleGraphic.setStyle({
label: {
color: '#000000',
},
});
}
});
// 监听点击事件
circleGraphic.on(mars3d.EventType.click, function () {
// 全部恢复默认
annotationRestoreDefault();
circleGraphic.setStyle({
label: {
color: item.properties.color,
},
});
emits('setNowShowAnnotationData', item);
});
// 将圆对象 添加到图层中
graphicLayers.addGraphic(circleGraphic);
// 数据
annotation_CircleGraphicData.push(circleGraphic);
}
});
};
// 地图标注-恢复默认
function annotationRestoreDefault() {
// 点-恢复默认
for (let i = 0; i < annotation_PointGraphicData.length; i++) {
let pointGraphic = annotation_PointGraphicData[i];
pointGraphic.setStyle({
label: {
color: '#000000',
},
});
}
// 线-恢复默认
for (let i = 0; i < annotation_LineStringGraphicData.length; i++) {
let lineGraphic = annotation_LineStringGraphicData[i];
lineGraphic.setStyle({
label: {
color: '#000000',
},
});
}
// 矩形-恢复默认
for (let i = 0; i < annotation_PolygonGraphicData.length; i++) {
let polygonGraphic = annotation_PolygonGraphicData[i];
polygonGraphic.setStyle({
label: {
color: '#000000',
},
});
}
// 圆形-恢复默认
for (let i = 0; i < annotation_CircleGraphicData.length; i++) {
let circleGraphic = annotation_CircleGraphicData[i];
circleGraphic.setStyle({
label: {
color: '#000000',
},
});
}
}
// 地图标注-SVG内容生成图片链接
function svgToDataURL(svgString: any) {
return 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgString)));
}
// 地图标注-绘制--------------------------------------------------------------------
const mapDrawType: any = ref('');
const drawColorPoint = ref('#2D8CF0');
const drawColorPolyline = ref('#2D8CF0');
const drawColorPolygon = ref('#2D8CF0');
const drawColorCricle = ref('#2D8CF0');
// 地图标注-绘制-点
async function drawPoint() {
if (mapDrawType.value == 'drawPoint') {
mapDrawType.value = '';
return;
}
mapDrawType.value = 'drawPoint';
let time = dayjs().format('YYYY-MM-DD HH:mm:ss');
const image = new Image();
image.crossOrigin = 'Anonymous';
image.src = svgToDataURL(defaultIcon.replaceAll('currentColor', drawColorPoint.value));
image.onload = () => {
// 创建Canvas元素
const canvas = document.createElement('canvas');
canvas.width = 30;
canvas.height = 40;
// 获取Canvas绘图上下文
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#00000000';
ctx?.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
const dataURL = canvas.toDataURL('image/png');
graphicLayers
.startDraw({
type: 'billboard',
style: {
image: dataURL,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
iconname: 'defaultIcon',
label: {
text: '点 ' + time,
font_size: 18,
color: '#000000',
outline: true,
outlineWidth: 6,
outlineColor: '#ffffff',
pixelOffsetY: -60,
},
},
})
.then((graphic) => {
annotation_PointGraphicData.push(graphic);
addAndUpdateWorkAnnotation(graphic, 'point', time);
});
};
}
// 地图标注-绘制-线
async function drawPolyline() {
if (mapDrawType.value == 'drawPolyline') {
mapDrawType.value = '';
return;
}
mapDrawType.value = 'drawPolyline';
let time = dayjs().format('YYYY-MM-DD HH:mm:ss');
const graphic = await graphicLayers.startDraw({
type: 'polyline',
style: {
width: 5,
line_start_cap: 0,
line_end_cap: 0,
color: drawColorPolyline.value,
label: {
text: '线 ' + time,
font_size: 18,
color: '#000000',
outline: true,
outlineWidth: 6,
outlineColor: '#ffffff',
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
pixelOffset: [25, -5],
},
},
});
annotation_LineStringGraphicData.push(graphic);
addAndUpdateWorkAnnotation(graphic, 'polyline', time);
}
// 地图标注-绘制-形状
async function drawPolygon() {
if (mapDrawType.value == 'drawPolygon') {
mapDrawType.value = '';
return;
}
mapDrawType.value = 'drawPolygon';
let time = dayjs().format('YYYY-MM-DD HH:mm:ss');
const graphic = await graphicLayers.startDraw({
type: 'polygon',
style: {
color: drawColorPolygon.value,
fill: false,
outline: true,
outlineColor: drawColorPolygon.value,
outlineWidth: 3,
label: {
text: '多边形 ' + time,
font_size: 18,
color: '#000000',
outline: true,
outlineWidth: 6,
outlineColor: '#ffffff',
},
},
});
annotation_PolygonGraphicData.push(graphic);
addAndUpdateWorkAnnotation(graphic, 'polygon', time);
}
// 地图标注-绘制-圆
async function drawCricle() {
if (mapDrawType.value == 'drawCricle') {
mapDrawType.value = '';
return;
}
mapDrawType.value = 'drawCricle';
let time = dayjs().format('YYYY-MM-DD HH:mm:ss');
const graphic = await graphicLayers.startDraw({
type: 'circle',
style: {
color: drawColorCricle.value,
fill: false,
outline: true,
outlineColor: drawColorCricle.value,
outlineWidth: 3,
label: {
text: '圆 ' + time,
font_size: 18,
color: '#000000',
outline: true,
outlineWidth: 6,
outlineColor: '#ffffff',
},
},
});
annotation_CircleGraphicData.push(graphic);
addAndUpdateWorkAnnotation(graphic, 'circle', time);
}
// 新增到数据库并刷新列表
async function addAndUpdateWorkAnnotation(graphic, annotationtype, time, addOrUpdate = 'add') {
let graphicJson = graphic.toJSON();
let params: any = {};
let coordinates = graphicJson.position || graphicJson.positions;
let properties = {};
let polygonData: any = [];
let type = 0;
let geom = '';
switch (annotationtype) {
case 'point':
type = 0;
geom = GeojsonToWkt(turf.point(coordinates).geometry);
properties = {
iconname: addOrUpdate == 'add' ? 'defaultIcon' : graphicJson.style.iconname,
font_size: 16,
iconnum: 0,
clampToGround: false,
color: addOrUpdate == 'add' ? drawColorPoint.value : graphicJson.style.label.color,
centerPoint: coordinates,
};
break;
case 'polyline':
type = 1;
geom = GeojsonToWkt(turf.lineString(coordinates).geometry);
properties = {
font_size: 16,
line_width: 5,
clampToGround: false,
color: drawColorPolyline.value,
centerPoint: coordinates[0],
line_start_cap: 0,
line_end_cap: 0,
};
break;
case 'polygon':
type = 2;
coordinates.push(coordinates[0]);
if (addOrUpdate == 'add') {
polygonData.push(coordinates);
} else {
polygonData = coordinates;
}
geom = GeojsonToWkt(turf.polygon(polygonData).geometry);
properties = {
font_size: 16,
clampToGround: false,
color: drawColorPolygon.value,
centerPoint: coordinates[0],
};
break;
case 'circle':
type = 3;
geom = GeojsonToWkt(turf.circle(coordinates, graphicJson.style.radius).geometry);
properties = {
font_size: 16,
clampToGround: true,
color: drawColorCricle.value,
radius: graphicJson.style.radius,
centerPoint: coordinates,
};
break;
}
if (addOrUpdate == 'add') {
params = {
name: graphicJson.style.label.text,
type: type,
properties: JSON.stringify(properties),
createTime: time,
createUser: '',
geom: geom,
workSpaceId: '1',
state: 0,
createUserName: '',
};
AddAnnotation(params).then((result) => {
// 刷新区域信息
emits('setAllAnnotationData');
mapDrawType.value = '';
});
} else {
params = {
id: graphicJson.id,
name: graphicJson.style.label.text,
type: type,
properties: JSON.stringify(properties),
geom: geom,
workSpaceId: '1',
state: props.nowShowAnnotationData.state,
};
UpdateAnnotation(params).then((result) => {
// 刷新区域信息
// emits('setAllAreaData');
// mapAreaDrawFlag.value = false;
});
}
}
// 图斑定位
const handlerLocation = (lngLat) => {
const position = Cesium.Cartesian3.fromDegrees(lngLat[0], lngLat[1]);
map.flyToPoint(position);
};
defineExpose({
handlerLocation,
annotationRestoreDefault,
});
onMounted(() => {
// let element = window.document.getElementsByClassName('mars3d-locationbar')[0] as HTMLElement;
// element.style.bottom = '40px';
});
</script>
<style lang="less" scoped>
.map-out-container {
width: 100%;
height: calc(100vh - 80px);
overflow: hidden;
}
.map-inner-container {
width: calc(100% + 80px);
height: calc(100% + 80px);
position: relative;
top: -40px;
// left: -40px;
}
.mars3d-container {
position: relative;
width: 100%;
height: 100%;
}
.annotationButtons {
position: absolute;
display: flex;
flex-wrap: wrap;
top: 10%;
right: 1%;
width: 30px;
height: 123px;
gap: 1px;
}
.button_nochoose {
background: #ffffff;
z-index: 200;
width: 30px;
height: 30px;
// border-radius: 3px;
display: flex;
align-items: center;
justify-content: center;
&:hover {
border: 2px solid #2b85e4;
outline: 1px solid #2b85e4;
}
}
.button_choose {
background: linear-gradient(to bottom left, #2b85e4 10px, transparent 1px), #ffffff;
background-size:
100% 100%,
auto;
z-index: 200;
width: 30px;
height: 30px;
// border-radius: 3px;
display: flex;
align-items: center;
justify-content: center;
outline: 2px solid #2b85e4;
}
.popoverAnnotation {
width: 18px;
height: 18px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 3px;
}
.popoverArea {
display: inline-flex;
align-items: center;
justify-content: flex-start;
width: 170px;
height: 35px;
}
</style>