引用依赖
import "ol/ol.css";import { Map, View, Feature } from "ol";import Vector from "ol/layer/Vector";import { Style, Fill, Stroke } from "ol/style";import { LineString } from "ol/geom";import TileLayer from "ol/layer/Tile";import XYZ from "ol/source/XYZ";import VectorLayer from "ol/layer/Vector";import VectorSource from "ol/source/Vector";import Draw from "ol/interaction/Draw";
加载地图
<div id="mapDiv" class={styles.mapBox}></div>
// 加载地图底图 const initMap = () => { // 创建一个地图 map.value = new Map({ // 存放地图的容器 target: "mapDiv", // 设置图层 layers: [ new TileLayer({ source: new XYZ({ url: "https://webrd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}", }), }), ], // 设置视图 view: new View({ center: [113.937705, 22.56225], // 中心点坐标 zoom: 14, // 缩放等级 maxZoom: 18, minZoom: 6, projection: "EPSG:4326", // 经纬度坐标 }), }); };
添加地图Draw交互
// 绘图事件 const drawInteraction = (value: any) => { if (draw.value) { map.value.removeInteraction(draw.value); } switch (value) { case "Cancel": // 取消绘制 break; case "Clear": // 清空绘制 // 绘制点位信息清空 ElMessageBox.confirm("确认清空当前绘制点位信息?", "绘制点位清空", { confirmButtonText: "确认", cancelButtonText: "取消", autofocus: false, type: "warning", }).then(() => { vectorSource.value = null; // 矢量图层源置空 if (vectorLayer.value) { vectorLayer.value.setSource(vectorSource.value); // 设置空的矢量图层源 } if (echoLayer.value) { echoLayer.value.setSource(vectorSource.value); // 设置空的矢量图层源 } map.value.removeLayer(vectorLayer.value); const params = { id: store.roadDetail.id, roadRangeData: [], }; store.drawPointSubmit(params).then((res) => { if (res.code === 200) { ElMessage.success("绘制点位信息清空成功"); store.searchRoadDetailById(route.query?.id as string); } else { ElMessage.error(res?.errorMessage || "绘制点位信息清空失败"); } }); }); break; case "LineString": // 绘制折线 drawFea( map, draw, vectorLayer, "LineString", vectorSource, undefined, false ); break; case "Polygon": // 不规则图形 drawFea( map, draw, vectorLayer, "Polygon", vectorSource, undefined, false ); break; default: drawFea( map, draw, vectorLayer, value, vectorSource, undefined, false ); } };
// 封装绘制图形函数 const drawFea = ( map: any, draw: any, layer: any, type: any, source: any, geometryFunction: any, freehand: any ) => { // 判断source是否为空,若为空,创建一个VectorSource对象,并设置为矢量图层的源 if (!layer.value) { layer.value = new VectorLayer(); } if (!source.value) { source.value = new VectorSource({ wrapX: false, }); map.value.addLayer(layer.value); } layer.value.setSource(source.value); // 创建绘图工具 draw.value = new Draw({ type, // 绘制图形类型 source: source.value, // 绘制的目标源 geometryFunction, // 绘图的几何函数 freehand, // 绘图时鼠标点击后是否松手进行绘制 style: new Style({ fill: new Fill({ color: "rgba(255, 255, 255, 0.5)", // 线下方区域的填充颜色(如果有需要) }), stroke: new Stroke({ color: "red", width: 5, lineDash: [10, 10], // 虚线的样式,[10, 10]表示线段为10px,间隔为10px lineCap: "square", // 线的末端样式 }), }), // 绘制图形的样式 }); // 给地图添加绘图交互 map.value.addInteraction(draw.value); // 监听绘制结束事件 draw.value.on("drawend", (event: any) => { const feature = event.feature; feature.setStyle( new Style({ fill: new Fill({ color: "rgba(255, 255, 255, 0.5)", // 线下方区域的填充颜色(如果有需要) }), stroke: new Stroke({ color: "red", width: 5, lineDash: [10, 10], // 虚线的样式,[10, 10]表示线段为10px,间隔为10px lineCap: "square", // 线的末端样式 }), }) // 绘制图形的样式 ); // const geometry = feature.getGeometry(); // const coordinates = geometry.getCoordinates(); // const params = { // id: store.roadDetail.id, // roadRangeData: coordinates, // }; // store.drawPointSubmit(params).then((res) => { // if (res.code === 200) { // ElMessage.success("绘制点位信息提交成功"); // store.searchRoadDetailById(route.query?.id as string); // } else { // ElMessage.error(res?.errorMessage || "绘制点位信息提交失败"); // } // }); }); };
Point:点 LineString: 线 Polygon: 面 Circle:圆
roadRangeData: coordinates[0] 多边形传参
roadRangeData: coordinates 点 线传参
绘制结束事件里面可以设置绘制完成后展示在地图里的样式和提交接口等自定义处理
路线点位提交
const drawSubmit = () => { if (!vectorSource.value) { ElMessage.error("请先绘制路线"); return; } const features = vectorSource.value.getFeatures(); if (features.length === 0) { ElMessage.error("请先绘制路线"); return; } const coordinates = features[0].getGeometry().getCoordinates(); if (!store.roadDetail.id) return; const params = { id: store.roadDetail.id, roadRangeData: coordinates, }; ElMessageBox.confirm("确认提交当前绘制点位信息?", "绘制点位提交", { confirmButtonText: "确认", cancelButtonText: "取消", autofocus: false, type: "warning", }).then(() => { store.drawPointSubmit(params).then((res) => { if (res.code === 200) { ElMessage.success("绘制点位信息提交成功"); store.searchRoadDetailById(route.query?.id as string); } else { ElMessage.error(res?.errorMessage || "绘制点位信息提交失败"); } }); }); };
将绘制完数据回显在地图
// 监听详情路线数据及时回显 watch( () => [store.roadDetail], () => { if ( Array.isArray(store.roadDetail?.roadRangeData) && store.roadDetail?.roadRangeData.length > 0 ) { let vectorSource = new VectorSource(); echoLayer.value = new Vector({ source: vectorSource, style: new Style({ fill: new Fill({ color: "rgba(255, 255, 255, 0.5)", // 线下方区域的填充颜色(如果有需要) }), stroke: new Stroke({ color: "red", width: 5, lineDash: [10, 10], // 虚线的样式,[10, 10]表示线段为10px,间隔为10px lineCap: "square", // 线的末端样式 }), }), // 绘制图形的样式 }); let plygon = new LineString(store.roadDetail?.roadRangeData, "XY"); let feature = new Feature({ geometry: plygon, }); vectorSource.addFeature(feature); map.value.addLayer(echoLayer.value); // 以路线中间坐标设置地图中心点 const view = map.value.getView(); const centerPoint = store.roadDetail?.roadRangeData[ Math.floor((store.roadDetail?.roadRangeData.length - 1) / 2) ]; view.setCenter(centerPoint); } } );
HTML结构
<div class={styles.roadInformation}> <p class={styles.title}>道路定位:</p> <div id="mapDiv" class={styles.mapBox}></div> <el-button type="primary" class={styles.btnWrap} onclick={() => drawInteraction("LineString")} > 绘制 </el-button> <el-button type="primary" class={styles.btnWrapCancel} onclick={() => drawInteraction("Cancel")} > 取消 </el-button> <el-button type="primary" class={styles.btnWrapClear} onclick={() => drawInteraction("Clear")} > 清空 </el-button> <el-button type="primary" class={styles.btnWrapSubmit} onclick={() => drawSubmit()} > 提交 </el-button> </div>