vue3+ts实现百度地图鼠标绘制多边形
百度地图api鼠标绘制地址: JavaScript API - 鼠标绘制 | 百度地图API SDK
index.vue文件引入组件
<map @submitMap="submitMap" />
import map from './components/map.vue';
//获取经纬度
const submitMap = (adress: any) => {const convertedData = convertCoordinates(adress);console.log(convertedData);
};
//使用 map 方法遍历数组,将每个对象转换为 [jd, wd] 形式的数组
function convertCoordinates(original: { jd: number; wd: number }[]): number[][] {return original.map((item) => [item.jd, item.wd]);
}
组件map.vue文件
<template><div :class="isFull ? 'fullContain' : 'contain'"><div id="allmap" :class="isFull ? 'fullMap' : 'allmap'"></div><divclass="dialog-footer"v-if="showClearButton":style="isFull ? 'height: 100%;width: 20%' : 'height: 500px'"><div class="content"><div class="title">编辑网格</div><div class="button-content"><el-button type="primary" @click="hzMap" v-if="showHzButton">绘制网格区域</el-button><el-button type="primary" @click="editMap" v-if="!showHzButton">编辑网格区域</el-button><el-button @click="clearnMap">清除网格区域</el-button></div><div class="title">使用说明</div><div class="tishi"><p>1.选择颜色,在地图上拖动鼠标绘制网格范围,绘制完成后双击鼠标左键完成绘制。</p><p>2.点击编辑按钮可对当前所绘网格区域进行修改。</p><p>3.点击清空按钮可清空当前所绘制的网格区域。</p><div class="button-content"><el-button type="primary" @click="mapSubimt">绘制完成</el-button></div></div></div><div :class="isFull ? 'sxFull' : 'allFull'" @click="fullClick"><el-icon color="#409efc"><FullScreen /></el-icon></div></div></div>
</template>
<script lang="ts" name="Post" setup>
// 定义 dts 数组中对象的类型
interface DtsItem {jd: number; // 经度wd: number; // 纬度
}// 修改 props 定义
const props = withDefaults(defineProps<{dts?: Array<DtsItem>; // 使用泛型 Array<DtsItem>}>(),{dts: () => [] // 默认值设为空数组}
);
const emit = defineEmits(['update:value']);
var map:any = null;
var polyline:any = null;
const mapPointList = ref([]);
var myGeo:any = null;
const showClearButton = ref(true);
const showHzButton = ref(true);
const isFull = ref(false);
watch(() => props.dts,() => {initEditMap();}
);
onMounted(() => {if (!map) {map = new window.BMapGL.Map('allmap');map.enableScrollWheelZoom(true);myGeo = new window.BMapGL.Geocoder();initMapWz();}
});const initMapWz = () => {let region = '陕西省';// if (JSON.parse(window.localStorage.getItem('authorities')).level == 1) {// region = JSON.parse(window.localStorage.getItem('authorities')).region01// } else if (JSON.parse(window.localStorage.getItem('authorities')).level == 2) {// region =// JSON.parse(window.localStorage.getItem('authorities')).region01 +// JSON.parse(window.localStorage.getItem('authorities')).region02// } else if (JSON.parse(window.localStorage.getItem('authorities')).level == 3) {// region =// JSON.parse(window.localStorage.getItem('authorities')).region01 +// JSON.parse(window.localStorage.getItem('authorities')).region02 +// JSON.parse(window.localStorage.getItem('authorities')).region03// } else if (JSON.parse(window.localStorage.getItem('authorities')).level == 4) {// region =// JSON.parse(window.localStorage.getItem('authorities')).region01 +// JSON.parse(window.localStorage.getItem('authorities')).region02 +// JSON.parse(window.localStorage.getItem('authorities')).region03 +// JSON.parse(window.localStorage.getItem('authorities')).region04// } else if (JSON.parse(window.localStorage.getItem('authorities')).level == 5) {// region =// JSON.parse(window.localStorage.getItem('authorities')).region01 +// JSON.parse(window.localStorage.getItem('authorities')).region02 +// JSON.parse(window.localStorage.getItem('authorities')).region03 +// JSON.parse(window.localStorage.getItem('authorities')).region04 +// JSON.parse(window.localStorage.getItem('authorities')).region05// }myGeo.getPoint(region, function (point:any) {if (point) {map.centerAndZoom(point, 16);} else {alert('您选择的地址没有解析到结果!');}});
};
const initEditMap = () => {if (map) {map.clearOverlays();if (props.dts.length > 0) {mapPointList.value = [];for (let item of props.dts) {const point = new window.BMapGL.Point(item.jd, item.wd);mapPointList.value.push(point);}showHzButton.value = false;polyline = new window.BMapGL.Polygon(mapPointList.value, {strokeColor: '#39c19e',strokeWeight: 2,strokeOpacity: 1,fillColor: '#39c19e'});map.addOverlay(polyline);}}
};
const uploadDTDW = (regionName:any) => {if (myGeo) {myGeo.getPoint(regionName, function (point:any) {if (point) {map.centerAndZoom(point, 16);} else {alert('您选择的地址没有解析到结果!');}});}
};
const editMap = () => {if (polyline.enableEditing) {if (mapPointList.value.length >= 2) {polyline.enableEditing();}}
};
const hzMap = () => {if (polyline) {polyline.disableEditing();}showHzButton.value = false;mzwg();
};
const mzwg = () => {map.addEventListener('click', function (e:any) {var point = new window.BMapGL.Point(e.latlng.lng, e.latlng.lat);mapPointList.value.push(point);if (mapPointList.value.length >= 2) {if (polyline != null) {polyline.setPath(mapPointList.value);} else {polyline = new window.BMapGL.Polygon(mapPointList.value, {strokeColor: '#39c19e',strokeWeight: 2,strokeOpacity: 1,fillColor: '#39c19e'});}map.addOverlay(polyline);}});map.addEventListener('dblclick', function (e:any) {map.removeEventListener('click');map.removeEventListener('mousemove');map.removeEventListener('dblclick');});map.addEventListener('mousemove', function (e:any) {if (mapPointList.value.length > 0) {if (polyline == null) {polyline = new window.BMapGL.Polygon([...mapPointList.value, new window.BMapGL.Point(e.latlng.lng, e.latlng.lat)],{strokeColor: '#39c19e',strokeWeight: 2,strokeOpacity: 1,fillColor: '#39c19e'});map.addOverlay(polyline);} else {polyline.setPath([...mapPointList.value,new window.BMapGL.Point(e.latlng.lng, e.latlng.lat)]);map.addOverlay(polyline);}}});
};
const removeOverlay = () => {if (polyline) {polyline.disableEditing();polyline = null;}showHzButton.value = true;map.clearOverlays();mapPointList.value = [];
};
const mapSubimt = () => {let point: { jd: number; wd: number }[] = []; // 初始化为空数组if (polyline) {point = getPoint();}if (isFull.value) {isFull.value = false;}emit('submitMap', point);
};const getPoint = (): { jd: number; wd: number }[] => {const point: { jd: number; wd: number }[] = [];const path = polyline.getPath();for (let index = 0; index < path.length; index++) {const currentPoint = path[index];const map = {jd: currentPoint.lng,wd: currentPoint.lat};// 使用 some 避免重复项if (!point.some(p => p.jd === map.jd && p.wd === map.wd)) {point.push(map);}}return point;
};
const clearnMap = () => {polyline = null;showHzButton.value = true;map.clearOverlays();mapPointList.value = [];// showHzButton.value = true// map.clearOverlays()// mapPointList = []
};
const init = (e:any) => {showClearButton.value = e;
};//绘制当前区域下所有的网格区域
const hadDrawWGXX = (e:any) => {e.forEach((contentItem:any) => {var points: any[] = [];var opts;contentItem.dts.forEach((item: { jd: any; wd: any; }, index: number) => {points.push(new BMapGL.Point(item.jd, item.wd));if (index == 0) {opts = {position: new BMapGL.Point(item.jd, item.wd), // 指定文本标注所在的地理位置offset: new BMapGL.Size(10, -40) // 设置文本偏移量};const label = new BMapGL.Label(contentItem.wgName, opts);label.setStyle({color: 'blue',borderRadius: '5px',borderColor: '#ccc',padding: '10px',fontSize: '16px',height: '40px',lineHeight: '20px'});map.addOverlay(label);label.disableMassClear();}});const polylineddd = new window.BMapGL.Polygon(points, {strokeColor: '#EBAF00',strokeWeight: 1,strokeOpacity: 1,fillColor: '#EBAF00',fillOpacity: 0.2});map.addOverlay(polylineddd);polylineddd.disableMassClear();});
};
const fullClick = () => {isFull.value = !isFull.value;
};const disgrogMap = () => {map.getOverlays().map((item: any) => {map.removeOverlay(item);});
};
</script><style lang="scss" scoped>
.contain {width: 100%;height: 455px;
}.fullContain {position: fixed;left: 0;top: 0;width: 100%;height: 100%;background-color: white;z-index: 99999;
}.allmap {width: 75%;height: 455px;float: left;
}.fullMap {width: 80%;height: 100%;float: left;
}.dialog-footer {float: right;width: 25%;height: 455px !important;border: 1px solid #e5e5e5;border-radius: 2px;.content {clear: both;margin-left: 20px;margin-right: 20px;.title {font-size: 20px;font-family: SourceHanSansCN-Medium, SourceHanSansCN;font-weight: 500;color: #333;height: 20px;line-height: 20px;border-left: 3px solid #188dff;padding-left: 10px;margin-bottom: 20px;margin-top: 20px;margin-bottom: 20px;}.tishi {font-size: 14px;height: 14px;line-height: 18px;.button-content {margin-top: 20px;}}.button-content {width: 100%;:deep(.el-button) {margin: 0px !important;width: 100%;margin-bottom: 10px !important;}}.hzwc {margin-top: 20px;}}
}.allFull {position: absolute;left: 70%;top: 15px;color: #39c19e;z-index: 100;font-size: 25px;
}.sxFull {position: absolute;left: 75%;top: 30px;color: #39c19e;z-index: 100;font-size: 25px;
}
</style>