CaiYuanYiTiHua/src/components/MapboxMaps/MapComponent.vue

1802 lines
48 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 class="map-container">
<div :id="mapContainerName" @mouseover="mapmouseover" class="map-box"></div>
<div class="cloud-query-div" v-if="props.geomsList" @click="initiateCloudQuery">
<div>
<div class="cloud-query-icon">
<Icon icon="gis:globe-poi" :size="20" />
</div>
<div>云查询</div>
</div>
</div>
<!-- 图层控制 -->
<div class="layer-control-center" v-if="false">
<a-collapse v-model:activeKey="activeKey" accordion expandIconPosition="end" expandIcon="">
<a-collapse-panel key="1" header="图层">
<p v-for="(item, index) in props.mapConfig.layers" class="layer-item">
<a-checkbox v-model:checked="item.checked" @change="handlerCheckboxChange(item)">{{
item.name
}}</a-checkbox>
</p>
<p v-for="(item, index) in props.mapConfig.baseLayers" class="layer-item">
<a-checkbox v-model:checked="item.checked" @change="handlerCheckboxChange(item)">{{
item.name
}}</a-checkbox>
</p>
</a-collapse-panel>
</a-collapse>
</div>
<!-- 绘图控制 -->
<div class="draw-control-center" v-show="drawing">
<div class="draw-btn" @click="handlerCancleDraw"> 取消 </div>
<div class="draw-btn" @click="handlerDrawComplete"> 保存 </div>
</div>
<!-- 根据输入坐标定位 -->
<div class="position-by-lnglat">
<a-tooltip>
<template #title>图斑定位</template>
<div class="to-location" @click="handlerToPosition()"></div>
</a-tooltip>
<a-tooltip>
<template #title>坐标定位</template>
<div class="draw-polygon" @click="LocationShow = true"></div>
</a-tooltip>
<a-tooltip>
<template #title>线分割图斑</template>
<div class="split-line" @click="handlerDrawLineString()" v-if="props.splitPlugin"></div>
</a-tooltip>
<a-tooltip>
<template #title>{{isShowPicture?'显示选中图片方位角':'显示全部图片方位角'}}</template>
<div :class="isShowPicture?'picture-azimuth':'picture-azimuth-active'" @click="handlerChangePictureVisible()"></div>
</a-tooltip>
<div class="split-polygon" @click="handlerDrawPolygon()" v-if="false"> </div>
</div>
<!-- 坐标输入框 -->
<div class="to-location-input" v-if="LocationShow">
<div class="location-operation">
<a-button type="default" size="small" @click="handlerPushLocationItem"
><PlusOutlined />添加</a-button
>
&nbsp;
<a-upload
name="file"
:before-upload="handleImportCoorinateChange"
:showUploadList="false"
>
<a-button
type="default"
size="small"
><CloudUploadOutlined />导入
</a-button>
</a-upload>
&nbsp;
<a-button type="default" size="small" @click="handlerClearLocationItem"
><ClearOutlined />清空</a-button
>
&nbsp;
<a-button
type="default"
size="small"
v-if="props.splitPlugin"
@click="onHandlerSplitPolygon"
><SplitCellsOutlined />分割图斑</a-button>
<span style="float: right">
<CloseOutlined @click="handlerLocationClose" />
</span>
</div>
<a-empty v-if="locationArrays.length == 0" />
<div class="location-item-list-coantienr">
<div class="location-item" v-for="(item, index) in locationArrays" :key="index">
<a-button type="default" size="small" @click="handlerLocationFlyTo(item)"
><EnvironmentOutlined
/></a-button>
<a-input
v-model:value="item.lng"
@chagne="handlerLocationChange"
addon-before=""
size="small"
style="width: 140px; margin: 0px 12px"
/>
<a-input
v-model:value="item.lat"
@chagne="handlerLocationChange"
addon-before=""
size="small"
style="width: 140px; margin-right: 12px"
/>
<a-button type="default" size="small" @click="handlerLocationRemove(index)"
><DeleteOutlined
/></a-button>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import {
onMounted,
onUnmounted,
defineProps,
defineEmits,
reactive,
ref,
defineExpose,
watch,
inject,
} from 'vue';
import { useMessage } from '@/hooks/web/useMessage';
import {
CloseOutlined,
EnvironmentOutlined,
DeleteOutlined,
CopyOutlined,
PlusOutlined,
ClearOutlined,
SplitCellsOutlined,
CloudUploadOutlined
} from '@ant-design/icons-vue';
import mapboxgl, { Map, Popup } from 'mapbox-gl';
import Icon from '@/components/Icon/Icon.vue';
// 图形绘制工具类
import MapboxDraw from '@mapbox/mapbox-gl-draw';
import { generateUUID, getGeometryCenter } from './src/tool';
// 测量工具
import { SwitchLayerControl, MeasureControl } from 'mapbox-extensions';
import 'mapbox-extensions/dist/index.css';
import U from 'mapbox-gl-utils';
import 'mapbox-gl/dist/mapbox-gl.css';
import './src/index.less';
import { MapboxConfig, MapboxDefaultStyle, MapControlConfig } from './src/config';
import { MP } from './src/MP';
import { DrawingType } from '@/enums/mapEnum';
// POLYGON分割函数
import { polygonCut } from './lib/segmentation';
import { splitPolygonByLine, splitPolygonByFill } from './lib/splitpolygon';
// 图片切换
import { userFormFileStore } from '@/store/modules/formFileUrl';
import { storeToRefs } from 'pinia';
import {
SnapPolygonMode,
SnapPointMode,
SnapLineMode,
SnapModeDrawStyles,
SnapDirectSelect,
} from 'mapbox-gl-draw-snap-mode';
import { customDrawStyles } from './Styles/Styles';
import Drawtool from '@/views/datamaintenance/components/drawtool.vue';
import { WktToGeojson, GeojsonToWkt } from './src/WktGeojsonTransform';
import { features } from 'process';
import { getAppEnvConfig } from '@/utils/env';
import { message, Modal } from 'ant-design-vue';
import { useCloudQueryStore } from '@/store/modules/cloudquery';
import { AddDroneTask } from '@/api/demo/cloudQuery.ts';
import proj4 from 'proj4'
// 投影转地理坐标系
function GkToCGCS2000(lngLat){
try{
// CGCS2000 / 3-degree Gauss-Kruger zone 39
let from_system = "+proj=tmerc +lat_0=0 +lon_0=117 +k=1 +x_0=39500000 +y_0=0 +ellps=GRS80 +units=m +no_defs +type=crs"
// China Geodetic Coordinate System 2000
// let to_system = "+proj=longlat +ellps=GRS80 +no_defs +type=crs";
// WGS 84 -- WGS84 - World Geodetic System 1984,
let to_system = "+proj=longlat +datum=WGS84 +no_defs +type=crs";
// transform
let trasnformLnglat = proj4(from_system,to_system,lngLat);
return trasnformLnglat;
}catch(e){
return null;
}
}
const useCloudQuery = useCloudQueryStore();
const { VITE_GLOB_API_URL } = getAppEnvConfig();
const VITE_GLOB_API_URL_VAR = ref<String>(VITE_GLOB_API_URL + '/');
const mapContainerName = ref<String>();
mapContainerName.value = 'mapContainer-' + generateUUID();
const openModal = ref(false);
const insertShpModal = ref(false);
const changeOpenModal = (value) => {
openModal.value = value;
};
const changeOpenInsertShpModal = (value) => {
insertShpModal.value = value;
};
// map参数类型
interface MapboxOptionsInterface {
mapOptions: mapboxgl.MapboxOptions;
control: DrawingType[];
}
const props = defineProps({
mapConfig: {
type: Object,
default: {},
},
layers: {
type: Array,
default: [],
},
location: {
type: Array,
default: [],
},
type: {
type: String,
default: '',
},
feature: {
type: String,
default: '',
},
splitPlugin: {
type: Boolean,
default: false,
},
geomsList: {
type: Array,
default: null,
},
caseno: {
type: String,
default: '',
}
});
let nextMapControl: Array<any> = reactive([]);
nextMapControl = props.control
? props.control.map((item) => {
return MapControlConfig[item];
})
: [];
// 定义地图容器
let map: Map;
let drawTool: any;
let popup: Popup;
let clickPoisition: Array<number> = [];
let selectFeature: Object = {};
let mp: any = null;
let geojson = reactive({
geojson: {},
});
let drawing = ref(false);
let drawGeojson = reactive({
geojson: {
type: 'FeatureCollection',
features: [],
},
});
let switchLayerControler;
const { createConfirm, createMessage } = useMessage();
// 定义地图回调emit
// 地图加载完成回调
const emit = defineEmits([
'mapOnLoad',
'mapDraw',
'handlerDrawComplete',
'handlerGetFormDetail',
'handlerSplitPolygon',
'onFeatureClick',
]);
watch(
() => props.mapConfig,
(newVal, oldVal) => {
handlerLoadMapLayer();
},
);
const formFileStore = userFormFileStore();
const formFileState = storeToRefs(formFileStore);
watch(formFileState.url, (newValue, oldValue) => {});
function mapmouseover(e) {}
onMounted(() => {
// let mapDiv = window.document.getElementById(mapContainerName.value);
// mapDiv?.onmouseover = function(e){
// alert(e);
// }
mapboxgl.accessToken = MapboxConfig.ACCESS_TOKEN;
map = initMap();
map.on('load', () => {
//挂载mapbox-gl-utils
U.init(map);
mp = new MP(map);
// 根据地图配置信息加载地形数据
if (props.mapConfig.mode == '3D') {
// handlerLoadTerrain();
}
// 初始化绘图空间
// handlerInitDrawTool(null);
map.on('click', (e) => {
// handlerPreviewFeatureInfo(e);
clickPoisition = e.lngLat;
});
map.on('draw.selectionchange', (e) => {
// handlerCopyToTargetLayer(e);
});
emit('mapOnLoad', map);
// 设置绘图监听事件
map.on('draw.create', function (e) {
drawGeojson.geojson.features = e.features;
handlerDealFeature(e.features[0]);
});
map.on('draw.update', function (e) {
drawGeojson.geojson = e.features;
handlerDealFeature(e.features[0]);
});
map.on('draw.delete', function (e) {
handlerDeleteFeature(e.features[0]);
});
window.handlerCopyFeature = handlerCopyFeature;
// 测量工具
map.addControl(
new MeasureControl({
horizontal: true, //default false
btnBgColor: '#ffffff', //default '#ffffff'
btnActiveColor: '#ddd', //default '#ddd'
geometryClick: true, //defualt false
enableModes: ['Point', 'LineString', 'Polygon'], //default all
onStart: () => {},
onStop: () => {},
measurePointOptions: {},
measureLineStringOptions: {},
measurePolygonOptions: {},
}),
'top-right',
);
// 加载图层
handlerLoadMapLayer();
// 应用图层绑定点击事件
// applicationLayers.forEach((item,index)=>{
// map.on("click",item.layer.id,(e)=>{
// let state = findLayerAttributeInfo(applicationLayers,e.features[0].layer.id);
// if(state){
// let formDetailParams = {
// attributeTable:state.attributeTable,
// attributeField:state.attributeField,
// value:e.features[0].properties.gid
// }
// // 调用父组件查询表单详情信息
// emit("handlerGetFormDetail",formDetailParams)
// createMessage.success("数据表:"+state.attributeTable+";查询字段:"+state.attributeField+"字段值:"+e.features[0].properties.gid)
// }else{
// createMessage.warning("当前点击图层未绑定信息");
// }
// })
// })
// 分割多边形
// splitFeature();
});
});
function handlerLayerChange() {
var allLayers = map.getStyle().layers;
if (map.getLayer('detailsLayerLine'))
map.moveLayer('detailsLayerLine', allLayers[allLayers.length - 1].id);
allLayers.forEach(function (layer) {});
// allLayers.forEach(function(layer){
// console.log("layersssss",layer.id);
// // map.moveLayer('detailsLayer', layer.id);
// });
}
// 地图图层控制
const handlerLoadMapLayer = () => {
if (switchLayerControler) {
// var allLayers = map.getStyle().layers;
// allLayers.forEach(function(layer){
// console.log("layerEEEEEE",layer);
// console.log(layer.id);
// // map.removeLayer(layer.id);
// });
// var allSources = Object.keys(map.style.sourceCaches);
// allSources.forEach(function(sourceId){
// map.removeSource(sourceId);
// });
map.removeControl(switchLayerControler);
}
let configlayers = {};
let baseLayers = [];
props.mapConfig.layers?.forEach((item, index) => {
let applicationLayers = [];
item?.layers?.forEach((it, idx) => {
let style = JSON.parse(it.style);
let layers = {
name: it.name,
layer: style,
fixed: true,
zoom: 18,
easeToOptions: {},
mutex: false,
mutexIdentity: generateUUID(),
active: it.checked,
backgroundImage: '',
backgroundImageActive: '',
selectAndClearAll: true,
selectAllLabel: 'select all',
clearAllLabel: 'clear all',
onVisibleChange: (visible: boolean) => {},
};
applicationLayers.push(layers);
});
configlayers[item.name] = {
uiType: 'SwitchBtn',
collapse: !0,
defaultCollapsed: !0,
layers: applicationLayers,
};
});
props.mapConfig.baseLayers?.forEach((item, index) => {
console.log('baselayers', item);
let layer = JSON.parse(item.style);
let image = item.image.replace('\\', '/');
let layers = {
name: item.name,
layer: layer,
fixed: false,
// zoom:0,
easeToOptions: {},
active: item.checked,
backgroundImage: VITE_GLOB_API_URL_VAR.value + image,
backgroundImageActive: '',
onVisibleChange: (visible: boolean) => {
handlerLayerChange();
},
};
console.log('layersssss', layers);
baseLayers.push(layers);
});
configlayers['地图底图'] = {
collapse: !0,
defaultCollapsed: !0,
uiType: 'ImgTxtBtn',
layers: baseLayers,
};
if (props?.mapConfig) {
if (props?.mapConfig?.baseLayers?.length > 0 && props?.mapConfig?.layers?.length > 0) {
// 图层管理工具
switchLayerControler = new SwitchLayerControl({
name: '图层管理',
position: 'top-left',
showToTop: true,
layerGroups: configlayers,
});
map.addControl(switchLayerControler, 'top-left');
}
}
handlerLayerChange();
};
// 销毁地图
const findLayerAttributeInfo = (layers, id) => {
let layer = layers?.find((itme, index) => {
return itme.layer.id == id;
});
if (layer) {
if (layer.layer.state) {
return layer.layer.state;
} else {
return false;
}
}
};
// 加载地形
const handlerLoadTerrain = () => {
map.addSource('mapbox-dem', {
type: 'raster-dem',
url: 'mapbox://mapbox.mapbox-terrain-dem-v1',
tileSize: 512,
maxzoom: 14,
});
map.setTerrain({ source: 'mapbox-dem', exaggeration: 1.5 });
};
// 移除地图实例
onUnmounted(() => {
map ? map.remove() : null;
});
// 数据绘制完成判断
const handlerDealFeature = (feature) => {
let existFeature = geojson.geojson.features.find((item, index) => {
return item.id == feature.id;
});
if (existFeature) {
// 如果查找到了 则替换数据
for (let i = 0; i < geojson.geojson.features.length; i++) {
if (geojson.geojson.features[i].id == feature.id) {
geojson.geojson.features[i] = feature;
}
}
} else {
// 如果没找到数据则添加到数组
geojson.geojson.features.push(feature);
}
// 自动将数据返回给父组件
handlerDrawComplete();
};
// 删除数据
const handlerDeleteFeature = (feature) => {
for (let i = 0; i < geojson.geojson.features.length; i++) {
if (geojson.geojson.features[i].id == feature.id) {
geojson.geojson.features.splice(i, 1);
}
}
// handlerDrawComplete();
};
// 初始化地图 返回地图实例
const initMap = () => {
return new mapboxgl.Map({
container: mapContainerName.value,
language: 'zh-cmn',
projection: 'equirectangular', // wgs84参考系
style: MapboxDefaultStyle,
// maxZoom: props.mapConfig.maxZoom ? props.mapConfig.maxZoom:18,
minZoom: props.mapConfig.minZoom ? props.mapConfig.minZoom : 1,
zoom: props.mapConfig.zoom ? props.mapConfig.zoom : 10,
pitch: props.mapConfig.angle ? props.mapConfig.angle : 0,
center: props.mapConfig.center?.split(',')
? props.mapConfig.center?.split(',')
: [118.340253, 35.092481],
});
};
const handlerMapControlClick = (handler: string) => {
handler === 'handlerDrawPoint' && handlerDrawPoint();
handler === 'handlerDrawLineString' && handlerDrawLineString();
handler === 'handlerDrawPolygon' && handlerDrawPolygon();
};
// 使用坐标点分割图斑
const onHandlerSplitPolygon = () => {
if (locationArrays.value.length < 2) {
createMessage.warning('必须绘制2个以上点');
} else {
let feature = {
type: 'Feature',
geometry: {
type: 'LineString',
coordinates: [],
},
};
locationArrays.value?.forEach((item, index) => {
if (item.lng && item.lat) {
let coor = [parseFloat(item.lng), parseFloat(item.lat)];
feature.geometry.coordinates.push(coor);
}
});
splitFeature(feature.geometry.coordinates);
}
};
// 分割图斑
const splitFeature = (line) => {
let splitLineString = {
type: 'Feature',
properties: {},
geometry: {
coordinates: line,
type: 'LineString',
},
};
let splitPolygon = currentGeoJson.value;
try {
// let features = polygonCut(splitPolygon,splitLineString,0.1,"meters");
let features = splitPolygonByLine(splitLineString, splitPolygon);
let splitAfterFeatures = {
type: 'FeatureCollection',
features: [],
};
splitAfterFeatures.features = features;
emit('handlerSplitPolygon', features);
handlerDetails(splitAfterFeatures);
handlerUnDraw();
} catch (e) {
createMessage.warning('分割线起点、终点需要在图斑外');
handlerUnDraw();
}
};
// 根据面分割
const splitFeatureByFill = (fill) => {
let splitLineString = {
type: 'Feature',
properties: {},
geometry: {
coordinates: [fill],
type: 'Polygon',
},
};
let splitPolygon = currentGeoJson.value;
// let features = polygonCut(splitPolygon,splitLineString,0.1,"meters");
let features = splitPolygonByFill(splitLineString, splitPolygon);
let splitAfterFeatures = {
type: 'FeatureCollection',
features: [],
};
splitAfterFeatures.features = [features];
handlerDetails(splitAfterFeatures);
handlerUnDraw();
};
//绘制点
const handlerDrawPoint = () => {
mp.draw('Point');
mp.on('Point', function (e) {
emit('mapDraw', 'Point', e);
});
};
//绘制线
const handlerDrawLineString = () => {
mp.draw('LineString');
mp.on('LineString', function (e) {
Modal.confirm({
title: '是否确认分割图斑?',
onCancel() {
handlerUnDraw();
},
async onOk() {
let coordinates = [];
e?.forEach((item, index) => {
coordinates?.push([item.lng, item.lat]);
});
splitFeature(coordinates);
},
});
emit('mapDraw', 'LineString', e);
});
};
//绘制面
const handlerDrawPolygon = () => {
mp.draw('Polygon');
mp.on('Polygon', function (e) {
let coordinates = [];
e?.forEach((item, index) => {
coordinates?.push([item.lng, item.lat]);
});
splitFeatureByFill(coordinates);
emit('mapDraw', 'Polygon', e);
});
};
//删除标记
const handlerUnDraw = () => {
mp.deleteDraw();
emit('mapDraw', 'cancel');
};
// 初始化绘图空间
const handlerInitDrawTool = (feature, bool) => {
// if (feature.features.length > 0) {
// feature.features.forEach((item) => {
// if (item.geometry.type == 'MultiPolygon') {
// let arr: any = ref([]);
// item.geometry.coordinates.forEach((val) => {
// arr.value.push(val[0]);
// });
// item.geometry.coordinates = arr.value;
// item.geometry.type = 'Polygon';
// }
// });
// }
geojson.geojson = feature;
if (drawTool) {
drawTool.deleteAll();
if (feature.features) {
drawTool.set(geojson.geojson);
}
} else {
drawTool = new MapboxDraw({
modes: {
...MapboxDraw.modes,
draw_point: SnapPointMode,
draw_polygon: SnapPolygonMode,
draw_line_string: SnapLineMode,
direct_select: SnapDirectSelect,
},
styles: customDrawStyles,
userProperties: true,
snap: true,
snapOptions: {
snapPx: 12, // defaults to 15
snapToMidPoints: true, // defaults to false
snapVertexPriorityDistance: 0.0025, // defaults to 1.25
},
guides: false,
});
map.addControl(drawTool, 'top-right');
if (feature.features) {
drawTool.set(geojson.geojson);
}
}
// 正在绘制
// if (bool) {
// drawing.value = true;
// } else {
// drawing.value = false;
// }
drawing.value = true;
};
// 将图斑复制到指定图层
const handlerCopyToTargetLayer = (e) => {
if (e.features.length > 0) {
if (popup) {
popup.remove();
popup = null;
}
selectFeature = e.features[0];
popup = new mapboxgl.Popup({
closeButton: false,
closeOnClick: false,
});
// 设置 popup 的位置和内容
popup
.setLngLat(clickPoisition)
.setHTML(
`
<div style="color:#333;padding:3px 12px;cursor:pointer;" type="primary" icon="el-icon-search" onclick="handlerCopyFeature();">复制当前图斑</div>`,
)
.addTo(map);
} else {
popup.remove();
}
};
const handlerCopyFeature = () => {
popup.remove();
createMessage.success('复制成功!');
};
// 添加到图层
const handlerAddToLayerList = (layer) => {
handlerCheckLayerExist(layer);
};
// 判断图层列表中是否一定添加
const handlerCheckLayerExist = (layer) => {
for (let i = 0; i < layerList.length; i++) {
if (layerList[i] == layer.id) {
return;
}
}
layerList.push(layer);
};
const handlerCheckboxChange = (item) => {
console.log('itemitemitem', item);
handlerPreviewLayer(item);
};
// 控制图层是否显示
const handlerPreviewLayer = (layer) => {
console.log('layersss', layer);
handlerLayerControler(layer);
};
// 图层控制中心
const handlerLayerControler = (layerInfo) => {
layerInfo.layer = layerInfo.layer ? layerInfo.layer : JSON.parse(layerInfo.style);
if (map.getSource(layerInfo.layer.id)) {
if (layerInfo.checked) {
map.setLayoutProperty(layerInfo.layer.id, 'visibility', 'visible');
} else {
map.setLayoutProperty(layerInfo.layer.id, 'visibility', 'none');
}
} else {
map.addLayer(layerInfo.layer);
map.on('click', layerInfo.layer.id, function (e) {
handlerPreviewFeatureInfo(e);
});
}
};
// 查看列表数据
const handlerDataList = () => {};
// 图斑属性查看
const handlerPreviewFeatureInfo = (e) => {
if (e.features) {
isOpen.value = true;
}
};
const handlerClose = (e) => {
isOpen.value = e;
};
const currentPosition = ref(null);
// 图斑定位
const handlerLocation = (lngLat) => {
map.flyTo({
center: lngLat,
zoom: 17,
speed: 10, // 飞行速度
curve: 1, // 飞行曲线
easing(t) {
// 飞行动画函数
return t;
},
});
};
// 定位
const handlerToPosition = () => {
if (currentPosition.value) {
map.flyTo({
center: currentPosition.value,
zoom: 17,
speed: 10, // 飞行速度
curve: 1, // 飞行曲线
easing(t) {
// 飞行动画函数
return t;
},
});
}
};
// 编辑图斑
const handlerEdit = (info) => {
initDraw(info);
};
const initDraw = (layerInfo) => {
// 实例化绘图工具
drawTool = new MapboxDraw({
modes: {
...MapboxDraw.modes,
draw_point: SnapPointMode,
// draw_polygon: SnapPolygonMode,
// draw_line_string: SnapLineMode,
direct_select: SnapDirectSelect,
},
styles: customDrawStyles,
userProperties: true,
snap: true,
snapOptions: {
snapPx: 15, // defaults to 15
snapToMidPoints: true, // defaults to false
snapVertexPriorityDistance: 0.0025, // defaults to 1.25
},
guides: false,
});
map.addControl(drawTool, 'top-right');
// let geojson:Object = {};
// if (layerInfo.dataType == "面") {
// geojson.type = "Polygon";
// geojson.coordinates = geojson.coordinates[0];
// } else if (layerInfo.dataType == "点") {
// geojson.type = "Point";
// geojson.coordinates = geojson.coordinates;
// } else if (layerInfo.dataType == "线") {
// geojson.type = "LineString";
// geojson.coordinates = geojson.coordinates[0];
// }
// if (formData.lat && formData.lng) {
// formData.lat = geojson.coordinates[1];
// formData.lng = geojson.coordinates[0];
// }
// geojson = {
// type: "FeatureCollection",
// features: [
// {
// type: "Feature",
// geometry: geojson,
// },
// ],
// };
// map.setLayoutProperty("pbfLayer", "visibility", "none");
// drawTool.set(geojson);
};
const handlerDrawComplete = () => {
let arr = [];
geojson.geojson.features.forEach((item, index) => {
let wktStr = GeojsonToWkt(item.geometry);
let obj = {
columnName: 'mapgeom',
value: wktStr,
};
arr.push(obj);
});
console.log('aaaa', arr);
emit('handlerDrawComplete', arr);
};
const handlerCancleDraw = () => {
if (drawTool) {
map.removeControl(drawTool);
drawTool = null;
drawing.value = false;
}
// 清空详情图层
if (map.getSource('detailsSource')) {
map.getSource('detailsSource').setData({
type: 'FeatureCollection',
features: [],
});
}
};
const handlerDraw = (status: string, features = null, bool = false) => {
let geo = {
type: 'FeatureCollection',
features: [],
};
// 清空详情图斑
if (map.getSource('detailsSource')) {
map.getSource('detailsSource').setData({
type: 'FeatureCollection',
features: [],
});
}
if (features == null) {
bool = true;
} else {
if (features.length > 0) {
for (let i = 0; i < features.length; i++) {
try {
let featureTemp = WktToGeojson(features[i]?.mapgeom);
let feature = {
id: generateUUID(),
type: 'Feature',
properties: {},
geometry: featureTemp,
};
geo.features.push(feature);
// 获取第一个图斑的中心点跳转定位
if (i == 0) {
let lngLat = getGeometryCenter(feature);
// let lngLat = getGeometryCenter(geo.features[0]);
currentPosition.value = lngLat;
handlerLocation(lngLat);
}
} catch (e) {
console.error('wktParse', e);
createMessage.error('WKT数据格式解析错误请检查WKT数据格式是否有误');
}
}
}
}
switch (status) {
case 'Add':
handlerInitDrawTool(geo, bool);
break;
case 'Edit':
handlerInitDrawTool(geo, bool);
break;
case 'Details':
handlerDetails(geo);
break;
default:
createMessage.error('请传入操作类型!');
}
};
const currentGeoJson = ref({});
const handlerDetails = (
geojson,
source = 'detailsSource',
layer = 'detailsLayer',
style = {
lineStyle: { 'line-color': '#fcf003', 'line-width': 3 },
fillStyle: { 'fill-color': '#fcf003', 'fill-opacity': 0.1 },
},
) => {
let fillLayerName = layer + 'Fill';
let lineLayerName = layer + 'Line';
if (source == 'detailsSource') {
console.log('currentGeoJson', geojson);
// 判断是单面还是多面
let coordinates = null;
if (geojson.features[0].geometry.type == 'MultiPolygon') {
coordinates = geojson.features[0].geometry.coordinates[0];
} else if (geojson.features[0].geometry.type == 'Polygon') {
coordinates = geojson.features[0].geometry.coordinates;
}
if (coordinates) {
if(
coordinates[0][coordinates[0].length - 1][0] ==
coordinates[0][coordinates[0].length - 2][0]
) {
coordinates[0]?.pop();
}
}
let singleFeature = {
type: 'Feature',
properties: {},
geometry: {
coordinates: coordinates,
type: 'Polygon',
},
};
currentGeoJson.value = singleFeature;
console.log('currentGeoJson', currentGeoJson.value);
}
if (map.getSource(source)) {
map.getSource(source).setData(geojson);
} else {
map.addSource(source, {
type: 'geojson',
data: geojson,
});
map.addLayer({
id: fillLayerName,
type: 'fill',
source: source,
layout: {},
paint: style.fillStyle,
});
map.addLayer({
id: lineLayerName,
type: 'line',
source: source,
layout: {},
paint: style.lineStyle,
});
map.on('click', fillLayerName, function (e) {
if (e.features.length > 0) {
var feature = e.features[0];
emit('onFeatureClick', feature);
}
});
}
};
// 创建查看图斑图层
// 粘贴坐标实现定位、绘图相关
interface LocationItem {
lng: string;
lat: string;
}
const LocationShow = ref<Boolean>(false);
const locationArrays = ref<LocationItem[]>([
// {"lat":3876411.9272,"lng":39624337.6595},
// {"lat":3876419.7281,"lng":39624444.1571},
// {"lat":3876419.8852,"lng":39624446.3011},
// {"lat":3876425.1275,"lng":39624517.8687},
// {"lat":3876425.2918,"lng":39624520.1122},
// {"lat":3876431.6438,"lng":39624606.8289},
// {"lat":3876412.7832,"lng":39624632.9065},
// {"lat":3876365.7135,"lng":39624644.6931},
// {"lat":3876325.9298,"lng":39624654.7128},
// {"lat":3876316.1075,"lng":39624657.1746},
// {"lat":3876246.0573,"lng":39624674.5737},
// {"lat":3876243.9623,"lng":39624675.0987},
// {"lat":3876243.8703,"lng":39624674.5037},
// {"lat":3876240.4283,"lng":39624652.4797},
// {"lat":3876233.6843,"lng":39624607.2316},
// {"lat":3876232.2352,"lng":39624597.5126},
// {"lat":3876222.6982,"lng":39624540.8865},
// {"lat":3876221.3592,"lng":39624531.5094},
// {"lat":3876215.2311,"lng":39624497.0364},
// {"lat":3876206.5951,"lng":39624498.5794},
// {"lat":3876189.579,"lng":39624390.1352},
// {"lat":3876189.002,"lng":39624386.4602},
// {"lat":3876186.4209,"lng":39624370.0092},
// {"lat":3876195.956,"lng":39624367.6201},
// {"lat":3876198.685,"lng":39624385.0072},
// {"lat":3876199.261,"lng":39624388.6822},
// {"lat":3876207.5961,"lng":39624441.8023},
// {"lat":3876209.7341,"lng":39624441.5433},
// {"lat":3876253.1836,"lng":39624436.2662},
// {"lat":3876258.4453,"lng":39624435.6273},
// {"lat":3876290.5054,"lng":39624431.7412},
// {"lat":3876299.4224,"lng":39624430.675},
// {"lat":3876303.8533,"lng":39624430.1453},
// {"lat":3876297.7186,"lng":39624342.1213},
// {"lat":3876299.3188,"lng":39624341.7203},
// {"lat":3876305.1635,"lng":39624340.2558},
// {"lat":3876387.1195,"lng":39624319.7203},
// {"lat":3876411.9272,"lng":39624337.6595}
]);
const locationGeoJson = reactive({
point: {
type: 'FeatureCollection',
features: [],
},
polyline: {
type: 'FeatureCollection',
features: [],
},
polygon: {
type: 'FeatureCollection',
features: [],
},
});
const handlerPushLocationItem = () => {
let item: LocationItem = {
lng: '',
lat: '',
};
locationArrays.value.push(item);
};
// 通过上传txt文件方式导入坐标数据
const handleImportCoorinateChange = (e)=>{
console.log("woligehoulai",e);
const reader = new FileReader();
reader.readAsText(e);
reader.onload = function(text){
console.log(text.target?.result?.split("\r\n"))
handlerImportCoor(text.target?.result?.split("\r\n"));
}
}
const handlerImportCoor = (arr)=>{
arr?.forEach((item,index)=>{
let coor = item.split(",");
if(coor[0] && coor[1]){
let obj = {
lng:parseFloat(coor[1]),
lat:parseFloat(coor[0])
}
locationArrays.value?.push(obj);
}
})
}
const handlerClearLocationItem = () => {
locationArrays.value = [];
locationGeoJson.point.features = [];
locationGeoJson.polygon.features = [];
locationGeoJson.polyline.features = [];
handlerLocationLoadLayer();
};
const handlerLocationClose = () => {
LocationShow.value = false;
};
const handlerLocationRemove = (index: number) => {
locationArrays.value.splice(index, 1);
handlerLocationGeoJson();
};
const handlerLocationChange = (e) => {};
// 定位跳转
const handlerLocationFlyTo = (item: LocationItem) => {
if(item.lng > 180){
let coor = GkToCGCS2000([parseFloat(item.lng),parseFloat(item.lat)]);
item.lng = coor[0];
item.lat = coor[1];
}
if (item.lng && item.lat) {
handlerLocation([item.lng, item.lat]);
handlerLocationGeoJson();
}
};
// 处理生成geojson数据
const handlerLocationGeoJson = () => {
locationGeoJson.point.features = [];
locationGeoJson.polyline.features = [];
locationGeoJson.polygon.features = [];
locationArrays.value?.forEach((item, index) => {
if (item.lng && item.lat) {
let feature = {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [parseFloat(item.lng), parseFloat(item.lat)],
},
};
locationGeoJson.point.features.push(feature);
}
});
if (locationArrays.value?.length >= 2) {
let feature = {
type: 'Feature',
geometry: {
type: 'LineString',
coordinates: [],
},
};
locationArrays.value?.forEach((item, index) => {
if (item.lng && item.lat) {
let coor = [parseFloat(item.lng), parseFloat(item.lat)];
feature.geometry.coordinates.push(coor);
}
});
feature.geometry.coordinates.push([
parseFloat(locationArrays.value[0].lng),
parseFloat(locationArrays.value[0].lat),
]);
locationGeoJson.polyline.features[0] = feature;
}
if (locationArrays.value?.length >= 3) {
let feature = {
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [[]],
},
};
locationArrays.value?.forEach((item, index) => {
if (item.lng && item.lat) {
let coor = [parseFloat(item.lng), parseFloat(item.lat)];
feature.geometry.coordinates[0].push(coor);
}
});
feature.geometry.coordinates[0].push([
parseFloat(locationArrays.value[0].lng),
parseFloat(locationArrays.value[0].lat),
]);
locationGeoJson.polygon.features[0] = feature;
}
handlerLocationLoadLayer();
console.log('locationGeoJson', locationGeoJson);
};
// 加载点、线、面图层
const handlerLocationLoadLayer = () => {
console.log("locationGeoJson123",locationGeoJson);
// 绘制点
if (map.getSource('LocationPointSource')) {
map.getSource('LocationPointSource').setData(locationGeoJson.point);
} else {
map.addSource('LocationPointSource', {
type: 'geojson',
data: locationGeoJson.point,
});
map.addLayer({
id: 'LocationPointLayer',
type: 'circle',
source: 'LocationPointSource',
paint: {
'circle-radius': 5,
'circle-color': '#408eff', // 设置点的颜色
},
});
}
// 绘制线
if (map.getSource('LocationPolylineSource')) {
map.getSource('LocationPolylineSource').setData(locationGeoJson.polyline);
} else {
map.addSource('LocationPolylineSource', {
type: 'geojson',
data: locationGeoJson.polyline,
});
map.addLayer({
id: 'LocationLineLayer',
type: 'line',
source: 'LocationPolylineSource',
paint: {
'line-color': '#408eff', // 设置线的颜色
'line-width': 2, // 设置线的宽度
},
});
}
// 绘制面
if (map.getSource('LocationPolygonSource')) {
map.getSource('LocationPolygonSource').setData(locationGeoJson.polygon);
} else {
map.addSource('LocationPolygonSource', {
type: 'geojson',
data: locationGeoJson.polygon,
});
map.addLayer({
id: 'LocationPolygonLayer',
type: 'fill',
source: 'LocationPolygonSource',
paint: {
'fill-color': '#408eff', // 设置填充颜色
'fill-opacity': 0.5, // 设置填充透明度
},
});
}
};
// 绘制图片方位角
// 是否显示全部方位角
const isShowPicture = ref<Boolean>(true);
const imageList = ref<Array>([]);
const pictureArrowElementArray = ref([]);
const pictureParentArrowElementArray = ref([]);
const currentPictureIndex = ref(null);
const currentPictureZIndex = ref(0);
function handlerLoadPictureAzimuth(list) {
imageList.value = list;
pictureArrowElementArray.value = [];
list.forEach((item, index) => {
if (item.lng && item.lat) {
let arrowElement = document.createElement('div');
arrowElement.className = 'picArrow';
arrowElement.style.width = '43px';
arrowElement.style.height = '57px';
let childElement = document.createElement('div');
childElement.className = 'childArrow';
childElement.style.width = '43px';
childElement.style.height = '57px';
childElement.style.transform = 'rotate(' + item.orientation + 'deg)';
childElement.style.backgroundImage = 'url(/map/arrow.png)';
childElement.style.backgroundSize = '43px 57px';
childElement.style.position = "relative";
arrowElement.appendChild(childElement);
pictureArrowElementArray.value?.push(childElement);
pictureParentArrowElementArray.value?.push(arrowElement);
let arrowMark = new mapboxgl.Marker(arrowElement)
.setLngLat([item.lng, item.lat])
.addTo(map);
}
});
currentPictureZIndex.value = list?.length;
// setTimeout(function(){
// handlerCurrentImageChange(0);
// },10000)
}
function handlerCurrentImageChange(fileName) {
// 根据图片名检索标签
let currentIndex = null;
imageList.value?.forEach((item, index) => {
if (item.filePath?.match(fileName)) {
currentIndex = index;
currentPictureIndex.value = index;
}
});
try {
pictureArrowElementArray.value?.forEach((itme, index) => {
pictureArrowElementArray.value[index].style.backgroundImage = 'url(/map/arrow.png)';
if(isShowPicture.value){
pictureArrowElementArray.value[index].style.display = 'block';
}else{
pictureArrowElementArray.value[index].style.display = 'none';
}
});
pictureArrowElementArray.value[currentIndex].style.backgroundImage = 'url(/map/arrow-a.png)';
pictureArrowElementArray.value[currentIndex].style.display = 'block';
// 设置显示在最上层
currentPictureZIndex.value = currentPictureZIndex.value + 1;
pictureParentArrowElementArray.value[currentIndex].style.zIndex = currentPictureZIndex.value;
} catch (e) {}
return;
}
function handlerChangePictureVisible(){
isShowPicture.value = !isShowPicture.value;
// 展示全部
if(isShowPicture.value){
pictureArrowElementArray.value?.forEach((itme, index) => {
pictureArrowElementArray.value[index].style.display = 'block';
});
}else{
pictureArrowElementArray.value?.forEach((itme, index) => {
pictureArrowElementArray.value[index].style.display = 'none';
});
if(pictureArrowElementArray.value?.length){
pictureArrowElementArray.value[currentPictureIndex.value].style.display = 'block';
}
}
// 展示选中
}
// 绘制点
const handlerLocationDrawPoint = () => {};
// 绘制线
const handlerLocationDrawLine = () => {};
// 绘制面
const handlerLocationDrawPolygon = () => {};
const initiateCloudQuery = () => {
if (useCloudQuery.getIdentification) {
message.warning('已有云查询运行,不能再次提交');
} else {
let geomidStr = props.geomsList.map((item) => item.key).join(',');
AddDroneTask({ geomid: geomidStr, caseno: props.caseno }).then((res) => {
message.success('成功提交云查询');
useCloudQuery.setIdentification(true);
});
}
};
defineExpose({
handlerDraw,
handlerDetails,
handlerLocation,
handlerCancleDraw,
handlerLoadPictureAzimuth,
handlerCurrentImageChange,
});
</script>
<style scoped>
.cloud-query-div {
position: absolute;
top: 50px;
left: 10px;
width: 52px;
height: 60px;
background: #fff;
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
border-radius: 5px;
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.1);
user-select: none;
cursor: pointer;
}
.cloud-query-icon {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 8px;
}
.map-container {
width: 100%;
height: 100%;
}
.map-box {
width: 100%;
height: 100%;
}
.layer-control-center {
position: absolute;
top: 15px;
left: 15px;
background: #fff;
border-radius: 8px;
}
.layer-control-center p {
margin: 0px;
}
.layer-control-center .ant-checkbox-wrapper {
}
.draw-control-center {
position: absolute;
padding: 8px;
top: 15px;
right: 15px;
background: #ffffff;
border-radius: 12px;
}
.draw-control-center .draw-btn {
float: left;
margin: 0px 7px;
padding: 5px;
border-radius: 5px;
}
.draw-control-center .draw-btn:hover {
background-color: rgb(0 0 0/5%);
cursor: pointer;
}
.mapboxgl-ctrl-group:not(:empty) {
box-shadow: none;
}
.mapboxgl-ctrl-group {
padding: 6px;
border-radius: 12px;
top: 5px;
right: 0px;
}
.mapbox-gl-draw_ctrl-draw-btn {
width: 20px !important;
height: 20px !important;
float: left;
}
.mapboxgl-ctrl-top-right {
width: 360px;
}
.mapboxgl-ctrl-group button + button {
border: 0px;
margin: 0px 6px;
}
.mapbox-gl-draw_ctrl-draw-btn:hover {
transform: scale(1.2);
}
.mapbox-gl-draw_polygon {
background-image: url(/polygon.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
}
.mapbox-gl-draw_point {
background-image: url(/point.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
}
.mapbox-gl-draw_line {
background-image: url(/line.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
margin: 0px 6px;
}
.mapbox-gl-draw_trash {
background-image: url(/del.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
}
.mapbox-gl-draw_combine {
background-image: url(/combine.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
}
.mapbox-gl-draw_uncombine {
background-image: url(/uncombine.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
}
.jas-ctrl-measure {
position: relative;
top: 6px;
right: 10px;
}
.jas-ctrl-measure-item {
height: 22px;
color: rgb(255, 255, 255);
}
.layer-item {
padding: 8px 16px;
}
.layer-item:hover {
background: #c7dcf580;
}
::v-deep .ant-collapse-content-box {
padding: 0px !important;
}
::v-deep .jas-ctrl-extend-desktop-container {
width: 320px !important;
}
.position-by-lnglat {
height: 29px;
background: #fff;
position: absolute;
top: 10px;
right: 131px;
border-radius: 3px;
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.1);
.to-location {
width: 29px;
height: 29px;
float: left;
background: url(/map/location.png);
background-size: 20px 20px;
background-repeat: no-repeat;
background-position: 4px 5px;
&:hover {
cursor: pointer;
}
}
.picture-azimuth{
width: 29px;
height: 29px;
float: left;
background: url(/map/is_show_picture.png);
background-size: 20px 20px;
background-repeat: no-repeat;
background-position: 4px 5px;
&:hover {
cursor: pointer;
}
}
.picture-azimuth-active{
width: 29px;
height: 29px;
float: left;
background: url(/map/not_show_picture.png);
background-size: 20px 20px;
background-repeat: no-repeat;
background-position: 4px 5px;
&:hover {
cursor: pointer;
}
}
.draw-polygon {
width: 29px;
height: 29px;
float: left;
background: url(/map/draw_polygon.png);
background-size: 20px 20px;
background-repeat: no-repeat;
background-position: 4px 5px;
&:hover {
cursor: pointer;
}
}
.split-line {
width: 29px;
height: 29px;
float: left;
background: url(/map/split_polygon.png);
background-size: 20px 20px;
background-repeat: no-repeat;
background-position: 4px 5px;
&:hover {
cursor: pointer;
}
}
.split-polygon {
width: 29px;
height: 29px;
float: left;
background: url(/map/split_polygon_polygon.png);
background-size: 20px 20px;
background-repeat: no-repeat;
background-position: 4px 5px;
&:hover {
cursor: pointer;
}
}
}
.to-location-input {
padding: 16px;
padding-right:4px;
width: 418px;
min-height: 60px;
background: #fff;
position: absolute;
top: 48px;
right: 10px;
border-radius: 5px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
.location-operation {
width: 100%;
height: 40px;
border-bottom: 1px solid #f1f1f1;
margin-bottom: 12px;
}
.location-item-list-coantienr{
width:100%;
max-height:400px;
overflow-y:auto;
.location-item {
line-height: 20px;
margin-bottom: 6px;
}
}
}
</style>