import * as KMap from "@/utils/ol-map/KMap"; import { Circle, Fill, Stroke, Style, Text, Icon } from "ol/style.js"; import LineString from "ol/geom/LineString"; import { newPoint } from "@/utils/map.js"; import Point from "ol/geom/Point"; import { Feature } from "ol"; import { Select } from 'ol/interaction'; import { platformModifierKeyOnly } from 'ol/events/condition'; /** * @description 地图层对象 */ class airLineStringLayer { constructor(map) { let that = this; this.vectorStyle = new KMap.VectorStyle(); this.lineStringLayer = new KMap.VectorLayer("lineStringLayer", 9999, { style: this.styleFunction, }); map.addLayer(this.lineStringLayer.layer); this.kmap = map; this.selectedFeatures = []; // 存储选中的要素 this.editMode = false; // 编辑模式标志 // 位置图标 this.pointLayer = new KMap.VectorLayer("pointLayer", 9999, { style: () => { return new Style({ image: new Icon({ src: require(`@/assets/images/map/drone-icon.png`), scale: 0.38, }), }); }, }); map.addLayer(this.pointLayer.layer); // 位置图标 this.pointOfflineLayer = new KMap.VectorLayer("pointOfflineLayer", 9999, { style: () => { return new Style({ image: new Icon({ src: require(`@/assets/images/map/drone-offline-icon.png`), scale: 0.38, }), }); }, }); map.addLayer(this.pointOfflineLayer.layer); // 添加选择交互 this.selectInteraction = new Select({ layers: [this.lineStringLayer.layer], style: this.getSelectStyle(), // 选中样式 toggleCondition: platformModifierKeyOnly, // 按住Ctrl键多选 multi: true // 允许多选 }); map.map.addInteraction(this.selectInteraction); // 监听选择变化 this.selectInteraction.on('select', (event) => { this.selectedFeatures = event.selected; }); } // 获取选中要素的样式 getSelectStyle() { return new Style({ image: new Circle({ radius: 16, stroke: new Stroke({ color: 'rgba(255, 0, 0, 0.7)', width: 3 }), fill: new Fill({ color: 'rgba(255, 0, 0, 0.3)' }) }), stroke: new Stroke({ color: 'rgba(255, 0, 0, 0.7)', width: 3 }) }); } // 进入编辑模式 enterEditMode() { this.editMode = true; this.selectInteraction.setActive(true); } // 退出编辑模式 exitEditMode() { this.editMode = false; this.selectInteraction.setActive(false); this.selectInteraction.getFeatures().clear(); this.selectedFeatures = []; } // 删除选中的点位 deleteSelectedPoints() { if (!this.editMode || this.selectedFeatures.length === 0) return; console.log('this.selectedFeatures', this.selectedFeatures); const source = this.lineStringLayer.layer.getSource(); // 删除选中的要素 this.selectedFeatures.forEach(feature => { source.removeFeature(feature); }); // 重新生成连线 this.regenerateLineString(); // 清空选择 this.selectedFeatures = []; this.selectInteraction.getFeatures().clear(); } // 重新生成连线 regenerateLineString() { const source = this.lineStringLayer.layer.getSource(); const features = source.getFeatures(); // 获取所有点要素并按pointIndex排序 const pointFeatures = features.filter(f => f.getGeometry().getType() === 'Point'); pointFeatures.sort((a, b) => { return parseInt(a.get('pointIndex')) - parseInt(b.get('pointIndex')); }); // 提取坐标数组 const coordinates = pointFeatures.map(feature => { const geom = feature.getGeometry(); return geom.getCoordinates(); }); // 删除旧的线要素 const lineFeatures = features.filter(f => f.getGeometry().getType() === 'LineString'); lineFeatures.forEach(f => source.removeFeature(f)); // 创建新的线要素 if (coordinates.length > 1) { const lineGeometry = new LineString(coordinates); const lineFeature = new Feature({ geometry: lineGeometry }); lineFeature.set("type", 'Online'); source.addFeature(lineFeature); } } styleFunction(feature) { const type = feature.get('type'); const geometry = feature.getGeometry(); const styles = []; // 处理线段的样式 if (geometry.getType() === 'LineString') { styles.push( new Style({ stroke: new Stroke({ color: type === 'Online' ? '#FFD689' : '#FFFFFF', width: 3, }), }) ); geometry.forEachSegment(function (start, end) { // 计算中间点坐标 const midX = (start[0] + end[0]) / 2; const midY = (start[1] + end[1]) / 2; const midPoint = [midX, midY]; // 计算线段方向角(弧度) const dx = end[0] - start[0]; const dy = end[1] - start[1]; const rotation = Math.atan2(dy, dx); // 添加箭头样式 styles.push( new Style({ geometry: new Point(midPoint), image: new Icon({ src: require(`@/assets/images/map/${type === 'Online' ? 'arrow' : 'arrow-offline'}-icon.png`), anchor: [0.5, 0.5], scale: 0.8, zIndex: 2, rotateWithView: true, rotation: -rotation, }), }) ); }); } // 处理点位的样式 if (geometry.getType() === 'Point') { styles.push( new Style({ image: new Icon({ src: require(`@/assets/images/map/${type === 'Online' ? 'air' : 'air-offline'}-icon.png`), scale: 1, displacement: [0, 20], }), }), new Style({ image: new Icon({ src: require(`@/assets/images/map/${type === 'Online' ? 'text' : 'text-offline'}-bj.png`), scale: 0.42, displacement: [5, 110], zIndex: 2, }), }), new Style({ text: new Text({ font: "18px PangMenZhengDao", text: feature.get('pointIndex') || '', // 显示顺序编号 offsetY: -47, fill: new Fill({ color: "#fff" }), }), }) ); } return styles; } initData(droneArr, dronePoint, name) { this.clearLayer(); //在线数据 const lineCoordinates = { type: 'Online', arr: droneArr }; // 创建线特征 let lineGeometry = new LineString(lineCoordinates.arr); let lineFeature = new Feature({ geometry: lineGeometry, }); lineFeature.set("type", lineCoordinates.type); this.lineStringLayer.addFeature(lineFeature); // 为每个点位创建单独的特征并设置顺序编号 lineCoordinates.arr.forEach((coord, index) => { let pointFeature = new Feature({ geometry: new Point(coord), }); pointFeature.set("type", lineCoordinates.type); pointFeature.set("pointIndex", (index + 1).toString()); // 设置从1开始的顺序编号 this.lineStringLayer.addFeature(pointFeature); }); // 添加无人机位置点 const pointVal = { id: 1, wkt: dronePoint, type: 'Online' }; let point = newPoint(pointVal, 'wkt'); this.pointLayer.addFeature(point); this.kmap.fit(this.lineStringLayer.source.getExtent(), { padding: [230, 230, 230, 230] }); } clearLayer() { this.lineStringLayer && this.lineStringLayer.layer.getSource().clear(); this.pointLayer && this.pointLayer.layer.getSource().clear(); this.pointOfflineLayer && this.pointOfflineLayer.layer.getSource().clear(); } } export default airLineStringLayer;