地图划区域的方法
import useComContainer from "./useComContainer";
declare type Data = Record<string, unknown>;
const { addCtrl:addComCtrl, removeCtrl: removeComCtrol} = useComContainer();
export default function useDialogContainer(){
let eleDiv: HTMLElement;
const parentContainer = document.querySelector('.dialog-container');
eleDiv = document.createElement('div');
eleDiv.className = 'dilogWrap'
parentContainer?.appendChild(eleDiv);
const addCtrl = (vueEle: any,option ?:Data | null) => {
return addComCtrl(eleDiv,vueEle,option);
};
const removeCtrl = () =>{
removeComCtrol();
}
const isEleExist = () => {
return !!eleDiv.childElementCount;
}
return {
addCtrl,
removeCtrl,
isEleExist,
}
}
区域组件列表-添加区域-弹窗
<template>
<div class="areaTable_add">
<el-button size="small" color="#1cb16f" @click="addBjdRow">添加区域</el-button>
</div>
<el-table
class="areaTable"
:data="props.areaList"
:size="'small'"
max-height="320"
:header-cell-style="{
color: '#fff',
backgroundColor: 'rgba(21, 29, 27, 1)',
borderColor: 'rgba(40, 58, 51, 1)',
padding: '0 0',
}"
:cell-style="{ backgroundColor: 'rgba(16, 19, 18, 1)', color: '#999999' }"
>
<el-table-column type="index" label="序号" align="center" width="100" />
<el-table-column prop="shape" label="区域类型" align="center">
<template #default="scope">
<span>{{ getValue(scope.row.shape, shapeType2) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button color="#f5494a" size="small" @click="deleteBjdRow(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script lang="ts">
export default {
name: 'areaTable',
};
</script>
<script lang="ts" setup>
import { reactive, toRefs, watch, onUnmounted } from 'vue';
import { getValue, shapeType2, removeArea } from '@/utils/dict';
import areaTypePlus from '../areaTypePlus/index.vue';
import useDialogContainer from '@/views/comprehensiveSituation/hooks/useDialogContainer';
import { localStorage } from '@/utils/storage';
const { addCtrl: addDialogCtrl, removeCtrl: removeDialogCtrl } = useDialogContainer();
interface Props {
areaList: any;
close: Function;
mapColor: string;
maplabel: string;
}
const props = withDefaults(defineProps<Props>(), {
areaList: [],
close: () => {},
mapColor: '',
maplabel: '',
});
const state = reactive<any>({
formData: {
shape: 3,
list: [{ flat: null, flon: null }],
coordsObj: {},
},
});
const { formData } = toRefs(state);
// 添加区域
const addBjdRow = () => {
localStorage.set('mapColor', props.mapColor);
localStorage.set('maplabel', props.maplabel);
addDialogCtrl(areaTypePlus, { close: props.close, formData: state.formData });
};
// 删除区域
const deleteBjdRow = (index: number, row: any) => {
localStorage.set('coordsRemove', 2);
props.areaList.splice(index, 1);
row.coordsObj.remove();
row.coordsObj.marker.remove();
};
// 编辑区域弹窗-保存添加区域列表上
const getareaSave = () => {
if (localStorage.get('coordsRemove') === 1) {
const obj = { ...state.formData };
props.areaList.push(obj);
}
};
// 监听目标数据的变化
watch(
() => state.formData,
() => {
getareaSave();
},
{
deep: true,
}
);
// 关闭弹窗清除地图区域
onUnmounted(() => {
removeArea(props.areaList);
});
</script>
<style lang="scss">
@import './style.scss';
</style>
添加区域弹窗组件
<template>
<el-dialog
v-model="dialogVisible"
class="taishi-dialog"
title="编辑区域"
draggable
width="24%"
:before-close="cancel"
>
<div class="areaType">
<el-form ref="formRef" :model="state.formDataPlus" :label-width="'100px'">
<el-form-item label="区域形状:">
<el-radio-group v-model="state.formDataPlus.shape" class="list_radio2" @change="getShape">
<el-radio :label="item.code" :key="item.code" v-for="item in shapeType2">{{ item.value }} </el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<el-divider />
<div>
<div class="areaType_add">
<el-button size="small" color="#1cb16f" @click="setArea">设置</el-button>
</div>
<el-table
class="areaType_table"
:data="state.formDataPlus.list"
:size="'small'"
max-height="320"
:header-cell-style="{
color: '#fff',
backgroundColor: 'rgba(21, 29, 27, 1)',
borderColor: 'rgba(40, 58, 51, 1)',
padding: '0 0',
}"
:cell-style="{ backgroundColor: 'rgba(16, 19, 18, 1)', color: '#999999' }"
>
<el-table-column type="index" label="序号" align="center" width="80">
<template #default="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column prop="flon" label="经度" align="center">
<template #default="scope">
<span
><el-input
type="number"
v-model="scope.row.flon"
placeholder="请输入"
clearable
@blur="getAreaData('flatFlon')"
/></span>
</template>
</el-table-column>
<el-table-column prop="flat" label="纬度" align="center">
<template #default="scope">
<span
><el-input
type="number"
v-model="scope.row.flat"
placeholder="请输入"
clearable
@blur="getAreaData('flatFlon')"
/></span>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button color="#1cb16f" size="small" @click="dt(scope.$index)">标点</el-button>
</template>
</el-table-column>
</el-table>
<el-form ref="formRef" :model="state.formDataPlus" :label-width="'120px'">
<div v-if="state.formDataPlus.shape === 3" class="elForm">
<el-form-item label="圆半径:">
<el-input
type="number"
style="width: 240px"
v-model="state.formDataPlus.circleRadius"
@blur="getAreaData('circleRadius')"
placeholder="请输入"
>
<template #suffix> 米 </template>
</el-input>
</el-form-item>
<el-form-item label="圆中心高度:" style="margin: 15px 0">
<el-input
type="number"
disabled
style="width: 240px"
v-model="state.formDataPlus.circleCenterHeight"
placeholder="请输入"
>
<template #suffix> 米 </template>
</el-input>
</el-form-item>
</div>
<div v-if="state.formDataPlus.shape === 4" class="elForm">
<el-form-item label="开始角度范围:" style="margin: 15px 0">
<el-input style="width: 240px" v-model="state.formDataPlus.startAngle" placeholder="请输入">
<template #suffix> 度 </template>
</el-input>
</el-form-item>
<el-form-item label="结束角度范围:" style="margin: 15px 0">
<el-input style="width: 240px" v-model="state.formDataPlus.stopAngle" placeholder="请输入">
<template #suffix> 度 </template>
</el-input>
</el-form-item>
</div>
</el-form>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="save"> 保存 </el-button>
<el-button @click="cancel">取消</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts">
export default {
name: 'areaType',
};
</script>
<script lang="ts" setup>
import { ref, reactive, toRefs, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
import { getComFixed3, getFlatFlon, shapeType2 } from '@/utils/dict';
import { localStorage } from '@/utils/storage';
import useCommandDraw from './useCommandDraw';
import useInterActionCircle from '@/views/comprehensiveSituation/hooks/useInterActionCircle';
import useInterActionPolygon from '@/views/comprehensiveSituation/hooks/useInterActionPolygon';
import L from 'leaflet';
const { addComMarker } = useCommandDraw();
const { drawCircle, cancelDraw } = useInterActionCircle();
const { drawPolygon, cancelDraw2 } = useInterActionPolygon();
const dialogVisible = ref(true);
const props = withDefaults(
defineProps<{
close: Function;
formData: any;
}>(),
{
close: () => {},
formData: {},
}
);
const state = reactive<any>({
formDataPlus: {
shape: 3,
list: [{ flat: null, flon: null }],
circleCenterHeight: 0,
coordsObj: {},
},
});
const { formDataPlus } = toRefs(state);
const getAreaData = (type: string) => {
if (state.formDataPlus.shape === 3 && type === 'flatFlon') {
state.formDataPlus.coordsObj.setLatLng(L.latLng(state.formDataPlus.list[0].flat, state.formDataPlus.list[0].flon));
}
if (state.formDataPlus.shape === 3 && type === 'circleRadius') {
state.formDataPlus.coordsObj.setRadius(state.formDataPlus.circleRadius);
}
if (state.formDataPlus.shape === 5 && type === 'flatFlon') {
const latLngs = state.formDataPlus.list.map((item: any, cIndex: number) => {
const latLng = L.latLng(item.flat, item.flon);
return latLng;
});
state.formDataPlus.coordsObj.setLatLngs(latLngs);
}
};
const save = () => {
if (state.formDataPlus.shape === 3) {
props.formData.shape = state.formDataPlus.shape;
props.formData.list = state.formDataPlus.list;
props.formData.circleRadius = state.formDataPlus.circleRadius;
props.formData.circleCenterHeight = state.formDataPlus.circleCenterHeight;
props.formData.coordsObj = state.formDataPlus.coordsObj;
} else if (state.formDataPlus.shape === 5) {
props.formData.shape = state.formDataPlus.shape;
props.formData.list = state.formDataPlus.list;
props.formData.coordsObj = state.formDataPlus.coordsObj;
}
localStorage.set('coordsRemove', 1);
cancel2();
};
const cancel = () => {
props.close();
dialogVisible.value = false;
cancelDraw();
cancelDraw2();
localStorage.set('coordsRemove', 2);
removeLayer();
};
const cancel2 = () => {
props.close();
dialogVisible.value = false;
};
const removeLayer = () => {
if (Object.keys(state.formDataPlus.coordsObj).length > 0) {
state.formDataPlus.coordsObj.remove();
state.formDataPlus.list = [{ flat: null, flon: null }];
state.formDataPlus.circleRadius = 0;
if (state.formDataPlus.coordsObj.marker) {
state.formDataPlus.coordsObj.marker.remove();
}
}
};
const getShape = async () => {
removeLayer();
if (state.formDataPlus.shape === 3) {
cancelDraw2();
const coords: any = await drawCircle();
state.formDataPlus.list = [
{ flat: getComFixed3(coords._latlng.lat, 6), flon: getComFixed3(coords._latlng.lng, 6) },
];
state.formDataPlus.circleRadius = getComFixed3(coords._mRadius, 2);
state.formDataPlus.coordsObj = coords;
console.log(coords);
state.formDataPlus.circleCenterHeight = 0;
} else if (state.formDataPlus.shape === 5) {
cancelDraw();
const coords: any = await drawPolygon();
state.formDataPlus.coordsObj = coords;
coords._latlngs[0].pop();
const latLngList = getFlatFlon(coords._latlngs[0]);
state.formDataPlus.list = latLngList;
}
};
const cases = () => {
switch (state.formDataPlus.shape) {
case 1:
state.formDataPlus.list = [{ flat: 39.846932, flon: 116.156543 }];
break;
case 2:
state.formDataPlus.list = [
{ flat: 39.846932, flon: 116.156543 },
{ flat: 39.845582, flon: 116.156872 },
];
break;
case 3:
state.formDataPlus.list = [{ flat: 39.846932, flon: 116.156543 }];
state.formDataPlus.circleRadius = 10000;
state.formDataPlus.circleCenterHeight = 0;
break;
case 4:
state.formDataPlus.list = [{ flat: 39.846932, flon: 116.156543 }];
state.formDataPlus.startAngle = 0;
state.formDataPlus.stopAngle = 360;
break;
case 5:
state.formDataPlus.list = [
{ flat: 39.846932, flon: 116.156543 },
{ flat: 39.845582, flon: 116.156872 },
{ flat: 39.844607, flon: 116.157784 },
{ flat: 39.843831, flon: 116.158367 },
{ flat: 39.843302, flon: 116.159316 },
];
break;
}
};
const setArea = () => {
removeLayer();
getShape();
};
const add = () => {
if (
(state.formDataPlus.shape === 1 || state.formDataPlus.shape === 3 || state.formDataPlus.shape === 4) &&
state.formDataPlus.list.length > 0
) {
return ElMessage.error('最多添加1个点');
}
const obj = { flon: null, flat: null };
state.formDataPlus.list.push(obj);
};
const dt = async (index: number) => {
const coords = (await addComMarker(index)) as number[];
state.formDataPlus.list[index].flon = getComFixed3(coords[1], 6);
state.formDataPlus.list[index].flat = getComFixed3(coords[0], 6);
getAreaData('flatFlon');
};
onMounted(() => {
getShape();
});
</script>
<style lang="scss">
.areaTypePlus {
width: 0 !important;
height: 0 !important;
}
.elForm {
margin-top: 5px;
}
</style>
<style lang="scss">
@import './style.scss';
</style>
引入区域组件具体页面
<template>
<div>
<el-form-item
:label="区域"
prop="areaList"
>
<areaTable :areaList="formData.areaList" />
</el-form-item>
</div>
</template>
<script setup lang="ts">
<areaTable :areaList="formData.areaList" />
<script>
// 区域解析-最终要的数据
const areaTypleList = getAreaTypleList(state.formData.areaList);
// 区域类型转化-按照指定的结构
export const getAreaTypleList = (arr: any) => {
const list = arr.map((item: any) => {
const obj: any = {
type: 'Feature',
geometry: {
type: null,
coordinates: [],
},
};
const { shape, list, circleRadius, startAngle, stopAngle } = item;
switch (shape) {
case 1: // 点 一维
obj.properties = {};
obj.geometry.type = 'Point';
obj.geometry.coordinates = getFlatFlonList(list)[0];
break;
case 2: //线 二维
obj.properties = [];
obj.geometry.type = 'LineString';
obj.geometry.coordinates = getFlatFlonList(list);
break;
case 3: // 圆 一维
obj.properties = {};
obj.geometry.type = 'Circle';
obj.geometry.radius = circleRadius;
obj.geometry.coordinates = getFlatFlonList(list)[0];
break;
case 4: // 扇形 一维
obj.properties = {};
obj.geometry.type = 'SemiCircle';
obj.geometry.startAngle = startAngle;
obj.geometry.stopAngle = stopAngle;
obj.geometry.coordinates = getFlatFlonList(list)[0];
break;
case 5: // 多边形 三维
obj.properties = [];
obj.geometry.type = 'Polygon';
obj.geometry.coordinates = [getFlatFlonList(list)];
break;
}
return obj;
});
return list;
};