前端代码
<template>
<Dialog title="地图" v-model="show" width="700px" top="5vh" center>
<div id="container-wrapper">
<baidu-map
class="bm-view"
:center="center"
:zoom="18"
:scroll-wheel-zoom="true"
@click="handleClick"
@mousemove="syncPolyline"
@rightclick="newPolyline"
>
<bm-control v-show="mode == 0">
<button @click.stop="toggle">{{ polyline.editing ? '停止绘制' : '开始绘制' }}</button>
<button @click.stop="clearPaths">{{ "清空绘制" }}</button>
</bm-control>
<!-- 标点模式 -->
<bm-marker v-if="mode == 1 && center" :position="center" :icon="markerIcon" />
<bm-marker v-if="mode == 1 && clickPosition" :position="clickPosition" :icon="markerIcon" />
<!-- 绘制模式 -->
<bm-polyline
v-for="(path, index) in polyline.paths"
:key="index"
:path="path"
:stroke-color="'blue'"
/>
</baidu-map>
</div>
<div v-if="mode === 1 && clickPosition" class="coordinates">
当前选中坐标: 经度 {{ clickPosition.lng }},纬度 {{ clickPosition.lat }}
</div>
<div v-if="mode == 0 && polyline.paths.length" class="coordinates">
当前绘制路径: {{ JSON.stringify(polyline.paths) }}
</div>
<template #footer>
<el-button @click="confirmAction" type="primary">确 定</el-button>
<el-button @click="cancelAction">取 消</el-button>
</template>
</Dialog>
</template>
<script setup>
import { ref ,toRef,nextTick} from "vue";
const show = ref(false);
const center = ref({ lng: 119.4196557630222, lat: 32.39979425018851 }); // 默认中心点
const clickPosition = ref(null); // 存储点击位置的经纬度
const mode = ref(1); // 模式,1为标点模式,0为绘制模式
const polyline = ref({
editing: false,
paths: []
}); // 绘制模式的路径
// 定义事件供父组件调用
const emit = defineEmits(["confirm"]);
// 显示地图模态框
const showModal = (params = {}) => {
console.log(polyline.value.paths);
center.value = {
lng: params.longitude ?? center.value.lng,
lat: params.latitude ?? center.value.lat,
};
if(params.footpathList!=[]){
polyline.value.paths = [params.footpathList._value];
}else{
polyline.value.paths = []; // 重置路径
}
clickPosition.value = null; // 重置选中位置
mode.value = params.mode ?? 1; // 设置模式
show.value = true;
};
// 点击事件处理
const handleClick = (e) => {
if (mode.value === 1) {
clickPosition.value = e.point; // 标点模式
} else if (mode.value === 0) {
paintPolyline(e); // 绘制模式
}
};
const toggle = (name) => {
if(polyline.value.editing){
// 停止绘制时清理未完成的点
cleanIncompletePath();
}
polyline.value.editing = !polyline.value.editing;
};
// 同步绘制的线
const syncPolyline = (e) => {
if (!polyline.value.editing) {
return
}
if (!polyline.value.paths.length) {
return
}
const path = polyline.value.paths[polyline.value.paths.length - 1]
if (!path.length) {
return
}
if (path.length === 1) {
polyline.value.paths[polyline.value.paths.length - 1].push(e.point)
}
polyline.value.paths[polyline.value.paths.length - 1][path.length - 1] = e.point;
};
// 清理未完成的路径(未闭合或单点的路径)
const cleanIncompletePath = () => {
if (polyline.value.paths && polyline.value.paths.length > 0) {
const currentPath = polyline.value.paths[polyline.value.paths.length - 1];
// 如果当前路径有点,移除最后一个点
if (currentPath && currentPath.length > 0) {
currentPath.pop();
}
}
};
// 开始新绘制线段
const newPolyline = () => {
if (!polyline.value.editing) {
return
}
console.log(polyline.value.paths);
if (!polyline.value.paths.length) {
polyline.value.paths.push([])
}
const path = polyline.value.paths[polyline.value.paths.length - 1]
path.pop()
if (path.length) {
polyline.value.paths.push([])
}
};
// 添加点到绘制路径
const paintPolyline = (e) => {
if (!polyline.value.editing) {
return
}
console.log(polyline.value.paths);
!polyline.value.paths.length && polyline.value.paths.push([])
polyline.value.paths[polyline.value.paths.length - 1].push(e.point)
};
// 确认操作
const confirmAction = () => {
if (mode.value === 1) {
emit("confirm", clickPosition.value,mode.value); // 返回标点坐标
} else if (mode.value === 0) {
emit("confirm", polyline.value.paths[0],mode.value); // 返回路径数据
}
show.value = false;
};
//清空绘制
const clearPaths = () => {
console.log(polyline.value.paths);
polyline.value.paths = []; // 清空所有路径
polyline.value.editing = false; // 停止绘制状态
};
const cancelAction = () => {
clickPosition.value = null; // 重置点击位置
clearPaths();
console.log(polyline.value.paths);
show.value = false; // 关闭对话框
};
// 暴露给父组件
defineExpose({ showModal });
</script>
<style lang="scss" scoped>
#container-wrapper {
position: relative;
width: 100%;
padding-bottom: 100%; /* 确保地图为正方形 */
overflow: hidden;
}
.bm-view {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.coordinates {
margin: 10px 0;
font-size: 14px;
color: #333;
}
</style>
后台管理效果如图