1161 lines
35 KiB
JavaScript
1161 lines
35 KiB
JavaScript
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: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
|
||
minZoom: 16,
|
||
maxZoom: 22
|
||
}),
|
||
cartodb: L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
|
||
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <a href="http://cartodb.com/attributions">CartoDB</a>',
|
||
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 <a href="http://stamen.com">Stamen Design</a>',
|
||
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 <a href="http://www.klokan.cz/projects/gdal2tiles/">GDAL2Tiles</a>';
|
||
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: `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||
<circle cx="12" cy="12" r="6" fill="#d81e06" stroke="#fff" stroke-width="1"/>
|
||
</svg>`,
|
||
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: `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||
<circle cx="12" cy="12" r="6" fill="#d81e06" stroke="#fff" stroke-width="1"/>
|
||
</svg>`,
|
||
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: `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||
<circle cx="12" cy="12" r="6" fill="yellow" stroke="#fff" stroke-width="1"/>
|
||
</svg>`,
|
||
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: `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||
// <circle cx="12" cy="12" r="6" fill="#d81e06" stroke="#fff" stroke-width="1"/>
|
||
// </svg>`,
|
||
// 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: `<div style="
|
||
color:#000;
|
||
padding: 2px 6px;
|
||
border-radius: 4px;
|
||
font-size: 12px;
|
||
transform: rotate(${-angle}deg);
|
||
white-space: nowrap;
|
||
">${this.formatDistance(lineLength)}</div>`
|
||
});
|
||
|
||
this.lengthMarker = L.marker([midLat, midLng], {
|
||
icon: this.lineLengthLabel,
|
||
interactive: false
|
||
}).addTo(this.map);
|
||
}
|
||
|
||
// =========================
|
||
// 计算角度
|
||
// =========================
|
||
calculateLineAngle(start, end) {
|
||
const dx = end[1] - start[1];
|
||
const dy = end[0] - start[0];
|
||
return (Math.atan2(dy, dx) * 180) / Math.PI;
|
||
}
|
||
|
||
// =========================
|
||
// 格式化距离
|
||
// =========================
|
||
formatDistance(meters) {
|
||
if (meters < 1000) return `${meters.toFixed(1)} m`;
|
||
return `${(meters / 1000).toFixed(2)} km`;
|
||
}
|
||
|
||
|
||
|
||
|
||
}
|