class MapManager { constructor(containerId, options = {}) { // 初始化地图配置 const defaultOptions = { center: [120.592946,41.201539], zoom: 16, minZoom: 8, maxZoom: 22, baseLayer: 'osm', // ✅ 默认底图改成 OSM satelliteLayerUrl: 'https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}' }; this.options = { ...defaultOptions, ...options }; // 初始化地图 this.map = L.map(containerId, { center: this.options.center, zoom: this.options.zoom, minZoom: this.options.minZoom, maxZoom: this.options.maxZoom }); this.map.createPane("pathPane"); this.map.getPane("pathPane").style.zIndex = 400; // 默认 overlayPane 是 400 // 初始化图层 this.initBaseLayers(); this.initOverlayLayers(); // 设置默认底图 & 覆盖层 this.setBaseLayer(this.options.baseLayer); this.setOverlayLayer('custom', true); // 添加图层控制 this.initLayerControl(); // 添加标题和说明 // this.initInfoControls(); // 存储绘制的元素 this.markers = []; this.polylines = []; this.polygons = []; this.imageOverlays = []; this.pointCenter = []; this.outerPoint = [];//十字准星 this.outerPoint1 = [];//机器打点 this.polylines = []; this.polygons = []; this.method = 2;//1:十字准星 2:机器 this.twopolyline = null;//两之间连线 this.savePath = null; this.mapStep = 1;//1作业区域2孔洞 this.distance = 0.8;//作业行距 this.completeFlag = false; this.polyLinePath = null; this.polyLineArea = null; this.planModel = 0;//0 弓字 1 回子 2 单点 this._outerPoints = [];//单点定位的打点 this.holePoints = [];//每一个孔洞的区域 this.markersHole = [];//打点孔洞的标记 this.holePointsList = [];//多个孔洞数组 this.isInit = false;//是否初始化过 this.isStopped = true; this.isPaused = true; this.workTypeStatus = null;//割草方法 this.selectedCutOption = '';//全局割草和局部割草 this.holeSideLine = [];//延边割草路径 this.polyLinePathClear = null;//清洗的线 this.initCenterMarker(); // this.enableClickPoint(); } generateRouteByWorkType() { if (this.workTypeStatus['巡检']) { fetch('./liaoning_inspection.json') .then(response => response.json()) .then(config => { this.drawPath(config, "pink",'',false,"巡检"); }) }else{ this.drawPath([], "pink",'',true,"巡检"); } if (this.workTypeStatus['清洗']) { fetch('./clear.json') .then(response => response.json()) .then(config => { this.drawPath(config, "purple",'',false,"清洗"); }) } else { this.drawPath([], "purple",'',true,"清洗"); } if (this.workTypeStatus['延边割草']) { fetch('./hole.json') .then(response => response.json()) .then(config => { this.drawLineHole(config,true) }) } else { this.drawLineHole() } if (this.workTypeStatus['割草']&&this.selectedCutOption=='全局割草') { this.generateRoute(); } } setOverlayLayer(layerName, visible) { if (visible) { this.map.addLayer(this.overlayLayers[layerName]); } else { this.map.removeLayer(this.overlayLayers[layerName]); } } setStatus(key, bool) { this[key]=bool } // 初始化底图 initBaseLayers() { this.baseLayers = { osm: L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors', minZoom: 16, maxZoom: 22 }), cartodb: L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors, © CartoDB', minZoom: 16, maxZoom: 22 }), satellite: L.tileLayer(this.options.satelliteLayerUrl, { attribution: '© Google Earth', minZoom: 16, maxZoom: 22 }), toner: L.tileLayer('http://{s}.tile.stamen.com/toner/{z}/{x}/{y}.png', { attribution: 'Map tiles by Stamen Design', minZoom: 16, maxZoom: 22 }), white: L.tileLayer("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAAA1BMVEX///+nxBvIAAAAH0lEQVQYGe3BAQ0AAADCIPunfg43YAAAAAAAAAAA5wIhAAAB9aK9BAAAAABJRU5ErkJggg==", { minZoom: 16, maxZoom: 22 }), // gaode: L.tileLayer( // 'https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}', // { // subdomains: ['0', '1', '2', '3'], // attribution: '© 高德地图', // minZoom: 3, // maxZoom: 18, // crossOrigin: true, // detectRetina: true // } // ) gaode: L.tileLayer( 'https://webst0{s}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', { subdomains: ['0', '1', '2', '3'], attribution: '© 高德地图', minZoom: 3, maxZoom: 22 } ) }; } setInit() { this.markers = []; this.polylines = []; this.polygons = []; this.imageOverlays = []; this.pointCenter = []; this.outerPoint = []; // 十字准星 this.outerPoint1 = []; // 机器打点 this.method = 2; // 1:十字准星, 2:机器 this.twopolyline = null; this.lineLengthLabel = null; this.lengthMarker = null; this.savePath = null; this.distance = 0.8; // 作业行距 this.completeFlag = false; this.polyLinePath = null; this.polyLineArea = null; this.planModel = 0; // 0 弓字 1 回字 2 单点 this.isStopped = true; } setMapStep(val) { this.mapStep = val; } // 初始化覆盖图层 initOverlayLayers() { this.overlayLayers = { custom: L.tileLayer('./{z}/{x}/{y}.png', { tms: 1, opacity: 1, attribution: "", minZoom: 16, maxZoom: 30 }) }; } setComplete(val) { this.completeFlag = val; } // 设置底图 setBaseLayer(layerName) { if (this.currentBaseLayer) { this.map.removeLayer(this.currentBaseLayer); } this.currentBaseLayer = this.baseLayers[layerName]; this.map.addLayer(this.currentBaseLayer); } setMethod(method) { this.method = method;//十字准星1还是机器打点 2 } // 初始化图层控制 initLayerControl() { const baseLayerControls = { "OpenStreetMap": this.baseLayers.osm, "CartoDB Positron": this.baseLayers.cartodb, "Satellite": this.baseLayers.satellite, "Gaode": this.baseLayers.gaode // ✅ 新增高德 }; const overlayControls = { "Custom Layer": this.overlayLayers.custom }; this.layerControl = L.control.layers( baseLayerControls, overlayControls, { collapsed: false } ).addTo(this.map); // 默认选中 custom this.overlayLayers.custom.addTo(this.map); } // 信息控件 initInfoControls() { const src = 'Generated by GDAL2Tiles'; const sourceControl = L.control({ position: 'bottomleft' }); sourceControl.onAdd = () => { this._sourceDiv = L.DomUtil.create('div', 'ctl src'); this._sourceDiv.innerHTML = src; return this._sourceDiv; }; sourceControl.addTo(this.map); } // 提供一个外部可设置的回调函数 setMoveEndCallback(callback) { this.onMapMoveEnd = callback; } initCenterMarker() { if (!this.isInit) { const center = this.map.getCenter(); const centerIcon = L.divIcon({ className: '', html: ``, iconSize: [24, 24], iconAnchor: [12, 12] }); this.centerMarker = L.marker(center, { icon: centerIcon, zIndexOffset: 1000 }).addTo(this.map); this.markers.push(this.centerMarker); } // this.pointCenter.push(center); this.map.on('move', () => { const newCenter = this.map.getCenter(); console.log(newCenter); this.centerMarker.setLatLng(newCenter); if (!this.completeFlag&&this.mapStep!=2) { this.drawTempLine(newCenter); } const pointdata = [...this.pointCenter, newCenter]; if (this.planModel!=2&&this.mapStep!=2) { this.drawPolygon(pointdata); } if (this.mapStep == 2) { this.drawPolygon(this.pointCenter); if (this.lengthMarker) { this.map.removeLayer(this.lengthMarker); this.lengthMarker = null; } } }); this.map.on('moveend', () => { const newCenter = this.map.getCenter(); this.centerMarker.setLatLng(newCenter); }); } // ---------------------- 点击打点 ---------------------- enableClickPoint() { if (this.method == 2) {//机器打点模式 } else {//十字准星模式 // 作业区域 if (this.mapStep == 1) { const newCenter = this.map.getCenter(); // this.outerPoint.push(wgsPoint); this.outerPoint.push(newCenter); this.pointCenter.push(newCenter); this.drawPolyline(); const clickIcon = L.divIcon({ className: '', html: ``, iconSize: [24, 24], iconAnchor: [12, 12] }); const marker = L.marker([newCenter.lat,newCenter.lng], { icon: clickIcon }).addTo(this.map); this.markers.push(marker); console.log(this.pointCenter, this.outerPoint); } else { const newCenter = this.map.getCenter(); // this.outerPoint.push(wgsPoint); this.holePoints.push(newCenter); const clickIcon = L.divIcon({ className: '', html: ``, iconSize: [24, 24], iconAnchor: [12, 12] }); const marker = L.marker([newCenter.lat,newCenter.lng], { icon: clickIcon }).addTo(this.map); this.markersHole.push(marker); } } // this.map.on('click', (e) => { // const point = e.latlng; // const wgsPoint = { // lng: coordtransform.gcj02towgs84(point.lng, point.lat)[0], // lat: coordtransform.gcj02towgs84(point.lng, point.lat)[1] // }; // this.outerPoint.push(wgsPoint); // this.pointCenter.push(point); // const clickIcon = L.divIcon({ // className: '', // html: ``, // iconSize: [24, 24], // iconAnchor: [12, 12] // }); // const marker = L.marker(point, { icon: clickIcon }).addTo(this.map); // this.markers.push(marker); // this.drawPolyline(); // this.drawPolygon(); // }); } setDistance(val) { this.distance = val; } setSingleOuterPoint(data) { this._outerPoints = data; if (this.lengthMarker) { this.map.removeLayer(this.lengthMarker); } if (this.twopolyline) this.map.removeLayer(this.twopolyline); if (this.lineLengthLabel) this.map.removeLayer(this.lineLengthLabel); } drawLineHole(holes, bool) { if (bool) { // 保存每个孔洞的中心点,用来画连接线 // 存放每个孔洞的第一个点 const firstPoints = []; // 先画每个孔洞的闭合线框 holes.forEach(hole => { // 转成 [lat, lon] const latlngs = hole.map(p => [p.lat, p.lon]); // 闭合 latlngs.push(latlngs[0]); // 画线框 this.holeSideLine.push(L.polyline(latlngs, { color: 'green', weight: 2 }).addTo(this.map)); // 收集每个孔洞的第一个点 firstPoints.push([hole[0].lat, hole[0].lon]); firstPoints.push([hole[hole.length-1].lat, hole[hole.length-1].lon]); }); // 再画连接每个孔洞第一个点的线 if (firstPoints.length > 1) { this.holeSideLine.push(L.polyline(firstPoints, { color: 'green', weight: 2 }).addTo(this.map)); } } else { if (this.holeSideLine.length >= 0) { this.holeSideLine.forEach(line => { line.remove(); }) } } } // ---------------------- 画折线 ---------------------- drawPolyline() { // 移除旧的折线 this.polylines.forEach(line => this.map.removeLayer(line)); this.polylines = []; if (this.pointCenter.length < 2) return; const polyline = L.polyline(this.pointCenter, { color: 'green', weight: 2 }).addTo(this.map); this.polylines.push(polyline); } // ---------------------- 画多边形 ---------------------- drawPolygon(data) { // 移除旧多边形 this.polygons.forEach(poly => this.map.removeLayer(poly)); this.polygons = []; if (data.length < 3) return; const polygon = L.polygon(data, { color: '#00ff00', fillOpacity: 0.2 }).addTo(this.map); this.polygons.push(polygon); } drawOuterLine(data) { const latlngs = data.map(p => { // const gcj = this.gaodePoint(p.lng, p.lat); // 转换为高德/GCJ-02坐标 const gcj = [p.lon, p.lat]; return [gcj[1], gcj[0]]; // Leaflet [lat, lng] }); L.polygon(latlngs, { color: '#00ff00', fillOpacity: 0.2 }).addTo(this.map); } drawHole(data) { debugger; const latlngs = data.map(subArr => subArr.map(item => ({ lat: item.lat, lon: item.lon }))); latlngs.forEach(item => { L.polygon(item, { color: '#00ff00', fillOpacity: 0.2 }).addTo(this.map); }) } setPlanModel(val) { this.planModel = val; } setHolePointsList() { this.holePointsList.push(this.holePoints); this.holePoints = []; } setWorkTypeStatus(data) { this.workTypeStatus = data; } setCutOption(data) { this.selectedCutOption = data; } generateRoute(angle) { console.log(angle, '角度'); let point_start, outer, holes; if (this.method == 1) { point_start = this.outerPoint[0]; outer = this.outerPoint.map(item => ({ lat: item.lat, lon: item.lng })); holes = this.holePointsList.map(subArr => subArr.map(item => ({ lat: item.lat, lon: item.lng })) ); // holes = this.holePoints.map(item => ({ lat: item.lat, lon: item.lng })); } else { point_start = this.outerPoint1[0]; outer = this.outerPoint1.map(item => ({ lat: item.lat, lon: item.lng })); // holes = this.holePoints.map(item => ({ lat: item.lat, lon: item.lng })); holes = this.holePointsList.map(subArr => subArr.map(item => ({ lat: item.lat, lon: item.lng })) ); } const queryParams = { reference: point_start ? { lat: point_start.lat, lon: point_start.lng } : {}, heading: angle||0, outer: outer, holes:holes, width: this.distance||0.8, workType: document.querySelector('input[name="plan"]:checked').value }; // const queryParams={ // "reference": { // "lat": 41.20159352618409, // "lon": 120.59300243854524 // }, // "heading": 90, // "outer":[{"lat":41.20159352618409,"lon":120.59308961033823},{"lat":41.20159554426899,"lon":120.59279456734659},{"lat":41.20155417351645,"lon":120.59271812438966},{"lat":41.20148555855214,"lon":120.59259608387949},{"lat":41.20140584401801,"lon":120.59250220656395},{"lat":41.201320075107006,"lon":120.59242174029353},{"lat":41.20122825179536,"lon":120.5923104286194},{"lat":41.20118385366439,"lon":120.59225007891655},{"lat":41.201166699833,"lon":120.5922004580498},{"lat":41.20115358219421,"lon":120.59211730957033},{"lat":41.20116266363672,"lon":120.59199929237367},{"lat":41.20116770888202,"lon":120.59190675616264},{"lat":41.20115459124343,"lon":120.59184372425081},{"lat":41.20113642835486,"lon":120.59179946780208},{"lat":41.20109909351256,"lon":120.59173777699472},{"lat":41.201065794851445,"lon":120.59168547391893},{"lat":41.201031487122265,"lon":120.59162646532062},{"lat":41.2010193785077,"lon":120.5915741622448},{"lat":41.201002224633186,"lon":120.59149101376535},{"lat":41.20098002549481,"lon":120.59142127633096},{"lat":41.20095681729662,"lon":120.59136226773263},{"lat":41.20092250951032,"lon":120.5913032591343},{"lat":41.200897283185384,"lon":120.5912482738495},{"lat":41.2008730659043,"lon":120.59118658304216},{"lat":41.20085086672213,"lon":120.59112757444385},{"lat":41.2008367399659,"lon":120.59109270572664},{"lat":41.20080142306198,"lon":120.59103906154634},{"lat":41.20077316952513,"lon":120.59098541736603},{"lat":41.2007348254199,"lon":120.59095188975334},{"lat":41.20058548500648,"lon":120.59092238545419},{"lat":41.20026258565029,"lon":120.59149235486987},{"lat":41.20026964909073,"lon":120.59170022606851},{"lat":41.200398809010444,"lon":120.59189602732658},{"lat":41.20046944323371,"lon":120.59199258685112},{"lat":41.20054108643944,"lon":120.59209719300272},{"lat":41.200578421600085,"lon":120.5922205746174},{"lat":41.2006601552558,"lon":120.59246733784678},{"lat":41.20078830534999,"lon":120.59268191456796},{"lat":41.20092654572141,"lon":120.59278652071956},{"lat":41.20104157763272,"lon":120.592869669199},{"lat":41.20119192605408,"lon":120.5929233133793},{"lat":41.20133218366597,"lon":120.59305742383005},{"lat":41.20142703396695,"lon":120.59311375021935}], // "holes": [ // [ // { // "lat": 41.20155417351645, // "lon": 120.5928632989526 // }, // { // "lat": 41.20155593934179, // "lon": 120.59303663671018 // }, // { // "lat": 41.201523397695766, // "lon": 120.5930306017399 // }, // { // "lat": 41.20152188413046, // "lon": 120.59285491704944 // } // ], // [ // { // "lat": 41.201426277183174, // "lon": 120.59267319738866 // }, // { // "lat": 41.20142173648036, // "lon": 120.59303462505342 // }, // { // "lat": 41.201390456074606, // "lon": 120.59302724897863 // }, // { // "lat": 41.20139348321131, // "lon": 120.59266783297063 // } // ], // [ // { // "lat": 41.20133319271244, // "lon": 120.59249013662341 // }, // { // "lat": 41.201330165572955, // "lon": 120.59284955263139 // }, // { // "lat": 41.20129812833821, // "lon": 120.59284519404174 // }, // { // "lat": 41.20130166000264, // "lon": 120.5924814194441 // } // ], // [ // { // "lat": 41.201205800471534, // "lon": 120.59249617159368 // }, // { // "lat": 41.20120554820942, // "lon": 120.59285860508682 // }, // { // "lat": 41.20117325865142, // "lon": 120.59285122901203 // }, // { // "lat": 41.20117426770036, // "lon": 120.59248711913827 // } // ], // [ // { // "lat": 41.201075633094, // "lon": 120.59174750000241 // }, // { // "lat": 41.201072605942606, // "lon": 120.59284653514624 // }, // { // "lat": 41.20104056858175, // "lon": 120.59284050017597 // }, // { // "lat": 41.20104410026008, // "lon": 120.5917414650321 // } // ], // [ // { // "lat": 41.20094975393033, // "lon": 120.59139579534532 // }, // { // "lat": 41.20094369961574, // "lon": 120.59268090873958 // }, // { // "lat": 41.20091140992856, // "lon": 120.59267487376931 // }, // { // "lat": 41.2009172119829, // "lon": 120.59139009565116 // } // ], // [ // { // "lat": 41.20083573091177, // "lon": 120.5911919474602 // }, // { // "lat": 41.20083219922218, // "lon": 120.59265911579134 // }, // { // "lat": 41.20079839589792, // "lon": 120.59265039861204 // }, // { // "lat": 41.20080848644428, // "lon": 120.59118658304216 // } // ], // [ // { // "lat": 41.20072927561335, // "lon": 120.59100687503816 // }, // { // "lat": 41.20072170769454, // "lon": 120.59247672557832 // }, // { // "lat": 41.20068790431322, // "lon": 120.5924727022648 // }, // { // "lat": 41.20069572450001, // "lon": 120.59100050479175 // } // ], // [ // { // "lat": 41.200630388072, // "lon": 120.59098005294801 // }, // { // "lat": 41.20062559504963, // "lon": 120.59208143502475 // }, // { // "lat": 41.20059330520548, // "lon": 120.59207607060674 // }, // { // "lat": 41.200598602759136, // "lon": 120.59097502380611 // } // ], // [ // { // "lat": 41.20054461814474, // "lon": 120.59118892997506 // }, // { // "lat": 41.200540077380765, // "lon": 120.59191815555097 // }, // { // "lat": 41.20050728296484, // "lon": 120.5919121205807 // }, // { // "lat": 41.20051106693673, // "lon": 120.5911832302809 // } // ], // [ // { // "lat": 41.20043563972209, // "lon": 120.59131868183613 // }, // { // "lat": 41.20043210801091, // "lon": 120.59186149388553 // }, // { // "lat": 41.20039981807132, // "lon": 120.59185680001976 // }, // { // "lat": 41.200403602049434, // "lon": 120.59131029993299 // } // ], // [ // { // "lat": 41.200330192834834, // "lon": 120.59151582419875 // }, // { // "lat": 41.200330192834834, // "lon": 120.59169083833697 // }, // { // "lat": 41.20029638925128, // "lon": 120.59168547391893 // }, // { // "lat": 41.20029790284496, // "lon": 120.59150844812395 // } // ] // ], // "width": this.distance, // "workType": "0" // } fetch('http://1.95.137.212:9527/api/path', { method: 'POST', headers: { 'Content-Type': 'application/json' }, mode: 'cors', body: JSON.stringify(queryParams) }) .then(res => res.json()) .then(data => { console.log('生成路径', data.data); // ===================== // 清除地图现有覆盖物 // ===================== this.clearMarkers(); // 添加中心标记 if (this.centerMarker) this.centerMarker.addTo(this.map); // 添加当前标记 // if (this.currentMarker) this.currentMarker.addTo(this.map); // 绘制路径 this.drawPath(data.data.path, "white"); // 绘制区域 this.drawArea(this.method == 1 ? this.outerPoint : this.outerPoint1, 'ccc'); // 保存路线信息 this.savePath = { path: data.data.path, outer: this.method == 1 ? this.outerPoint : this.outerPoint1, img: '', name: '', planModel: this.planModel }; // 可选:调用外部接口 // RPJavaInterface.generatePointToJava(data.data); }) .catch(err => console.error('Error:', err)); } saveArea(data) { this.savePath = data; } gaodePoint(lon, lat) { const point = coordtransform.wgs84togcj02(lon, lat); return point;//数组 } // 绘制路径 // ========================= drawPath(points, color = 'white', type = 'gaode', bool,worktype) { if (!bool) { if (!points || points.length < 2) { console.error("至少需要两个点才能绘制路径"); return; } // 生成 Leaflet 坐标数组 const latlngs = points.map(p => { if (type !== 'gaode') { // const gcj = this.gaodePoint(p.lon || p.lng, p.lat); const gcj = [p.lon || p.lng, p.lat]; return [gcj[1], gcj[0]]; // Leaflet: [lat, lng] } else { return [p.lat, p.lon]; } }); if (worktype == "巡检") { if (this.polyLinePath) { this.polyLinePath.remove() } // 绘制折线 this.polyLinePath = L.polyline(latlngs, { color, weight: 2, opacity: 1, pane: "pathPane" }); this.polyLinePath.addTo(this.map); } else if (worktype == "清洗") { if (this.polyLinePathClear) { this.polyLinePathClear.remove() } // 绘制折线 this.polyLinePathClear = L.polyline(latlngs, { color, weight: 2, opacity: 1, pane: "pathPane" }); this.polyLinePathClear.addTo(this.map); } } else { if (this.polyLinePath&&worktype=="巡检") { this.polyLinePath.remove() } if (this.polyLinePathClear&&worktype=="清洗") { this.polyLinePathClear.remove() } } } drawOuter(data) { const latlngs = data.map(p => { // const gcj = this.gaodePoint(p.lng, p.lat); // 转换为高德/GCJ-02坐标 const gcj = [p.lon, p.lat]; return [gcj[1], gcj[0]]; // Leaflet [lat, lng] }); this.polyLineArea = L.polygon(latlngs, { color: 'transparent', fillColor: 'yellow', fillOpacity: 0.2, weight: 2, opacity: 0.7 }); this.polyLineArea.addTo(this.map); // 可选:自动适配视野 this.map.fitBounds(this.polyLineArea.getBounds()); } // ========================= // 绘制多边形 // ========================= drawArea(points, color = '#ccc', isClosed = true) { if (!points || points.length < 3) return null; // 清除上一次的多边形 // 生成 Leaflet 坐标数组 const latlngs = points.map(p => { // const gcj = this.gaodePoint(p.lng, p.lat); // 转换为高德/GCJ-02坐标 const gcj = [p.lng, p.lat]; return [gcj[1], gcj[0]]; // Leaflet [lat, lng] }); if (this.polyLineArea) { this.polyLineArea.remove(); } this.polyLineArea = L.polygon(latlngs, { color: 'transparent', fillColor: color, fillOpacity: 0.2, weight: 2, opacity: 0.7 }); this.polyLineArea.addTo(this.map); // 可选:自动适配视野 this.map.fitBounds(this.polyLineArea.getBounds()); return this.polyLineArea; } clearAllLayer() { // 清除线段 if (this.twopolyline) { this.map.removeLayer(this.twopolyline); this.twopolyline = null; } if (this.polyLinePath) { this.map.removeLayer(this.polyLinePath); this.polyLinePath = null; } if (this.polyLineArea) { this.map.removeLayer(this.polyLineArea); this.polyLineArea = null; } // 清除测量长度文本 if (this.lengthMarker) { this.map.removeLayer(this.lengthMarker); this.lengthMarker = null; } // 批量清除 marker if (this.markers && this.markers.length > 0) { this.markers.forEach(m => this.map.removeLayer(m)); this.markers = []; } // 批量清除 polyline if (this.polylines && this.polylines.length > 0) { this.polylines.forEach(l => this.map.removeLayer(l)); this.polylines = []; } // 批量清除 polygon if (this.polygons && this.polygons.length > 0) { this.polygons.forEach(p => this.map.removeLayer(p)); this.polygons = []; } this.pointCenter = []; this.outerPoint = []; this.outerPoint1 = []; this.isInit = true; this.initCenterMarker(); } undoLastPoint() { console.log('撤回'); switch (this.mapStep) { // 作业区域模式 case 1: if (this.method == 1) { // 十字准星模式 this.outerPoint.splice(-1); this.pointCenter.splice(-1); this._outerPoints = this.outerPoint; const center = this.map.getCenter(); this.drawTempLine(center); // 对应 handleLine this.drawPolyline(); if (this.planModel != 2) { this.drawPolygon(this.pointCenter); } const lastMarker = this.markers.pop(); // 从数组中移除最后一个并返回 // 从地图上移除这个 marker if (lastMarker) this.map.removeLayer(lastMarker); // if (this.planModel !== 2) { // this.updateOuter(this.pointCenter, 'gaode'); // this.handleArea(center); // this.drawPath(this.pointCenter, "white", 'gaode'); // } else { // // this.drawPath(this.pointCenter, "white", 'gaode'); // } if (this.outerPoint1.length === 0) { this.clearAllOverlays(); this.map.addLayer(this.centerMarker); // if (this.currentMarker) this.map.addLayer(this.currentMarker); } } else { // 机器打点模式 this.map.remove(this.markers); this.outerPoint.splice(-1); this._outerPoints = this.outerPoint1; this.markers.splice(-1); this.markers.forEach(m => this.map.addLayer(m)); if (this.planModel !== 2) { this.updateOuter(this.outerPoint); } else { this.drawPath(this.outerPoint, "white"); } if (this.outerPoint.length === 0) { this.clearAllOverlays(); this.map.addLayer(this.centerMarker); if (this.currentMarker) this.map.addLayer(this.currentMarker); } } break; case 2: if (this.method === 1) { this.map.remove(this.markerHole1); this.holePoints1.splice(-1); this.markerHole1.splice(-1); this.markerHole1.forEach(m => this.map.addLayer(m)); this.updateHole(this.holePoints1); } else { this.map.remove(this.markerHole); this.holePoints.splice(-1); this.markerHole.splice(-1); this.markerHole.forEach(m => this.map.addLayer(m)); this.updateHole(this.holePoints); } break; } } // ---------------------- 移除所有标记 ---------------------- clearMarkers() { this.markers.forEach(m => this.map.removeLayer(m)); this.markers = []; this.markersHole.forEach(m => this.map.removeLayer(m)); this.markersHole = []; this.holePoints = []; this.pointCenter = []; this.polylines.forEach(l => this.map.removeLayer(l)); this.polylines = []; this.polygons.forEach(p => this.map.removeLayer(p)); this.polygons = []; // this.map.remove(this.twopolyline); this.twopolyline = null; if (this.lengthMarker) { this.lengthMarker.remove(); } } drawTempLine(centerPoint) { let point; console.log(this.method, '当前模式'); if (this.method == 1) { // 十字准星模式 console.log(this.pointCenter,"打点") if (this.pointCenter.length === 0) { if (this.twopolyline) this.map.removeLayer(this.twopolyline); if (this.lineLengthLabel) this.map.removeLayer(this.lineLengthLabel); return; } point = this.pointCenter[this.pointCenter.length - 1]; console.log(point,98888) } else { // 机器打点模式 // if (this.outerPoint.length === 0) { // if (this.lineLengthLabel) this.map.removeLayer(this.lineLengthLabel); // return; // } return; // 直接退出(你原代码就是这样处理的) } const points = [point, centerPoint].map(item => ({ lng: item.lng, lat: item.lat })); if (this.twopolyline) this.map.removeLayer(this.twopolyline); if (this.lineLengthLabel) this.map.removeLayer(this.lineLengthLabel); const latlngs = points.map(p => [p.lat, p.lng]); // Leaflet 坐标数组 // 创建虚线 this.twopolyline = L.polyline(latlngs, { color: '#ccc', weight: 2, opacity: 1, dashArray: '5,5' }).addTo(this.map); // 计算长度(米) const lineLength = this.map.distance(latlngs[0], latlngs[1]); // 计算中点 const midLat = (latlngs[0][0] + latlngs[1][0]) / 2; const midLng = (latlngs[0][1] + latlngs[1][1]) / 2; // 计算角度(相对水平方向) const angle = this.calculateLineAngle(latlngs[0], latlngs[1]); if (this.lengthMarker) { this.lengthMarker.remove(); } // 添加文字标注 this.lineLengthLabel = L.divIcon({ className: '', html: `