import { ILayer } from "@antv/l7-core"; import { LineLayer, PointLayer } from "@antv/l7-layers"; import { featureCollection, lineString, LineString } from "@turf/turf"; import HPaaSL7 from "../../HPaaSL7"; import { Popup } from "@antv/l7"; import { splitMultiPolygonByLine } from "./utils"; import ToolBase from "../base/ToolBase"; import { LineSplitEventMap } from "../../types"; import { PolygonFeatureType } from "../data/PolygonStore"; interface GeoPoint { lng: number; lat: number; } class LineSplit extends ToolBase { private hpaas: HPaaSL7; isSplitting = false; private pointLayer!: ILayer; private shapeLayer!: ILayer; private popup!: Popup; /** 已经绘制的点 */ private drawingPoints: GeoPoint[] = []; /** 跟随鼠标移动的点 */ private movingPoint: GeoPoint = { lat: 0, lng: 0 }; private splittingFeature!: PolygonFeatureType; constructor(hpaas: HPaaSL7) { super(); this.hpaas = hpaas; this.createLayer(); } private createLayer() { this.pointLayer = new PointLayer({ zIndex: 1001, pickingBuffer: 2, }) .source([], { parser: { type: "json", x: "lng", y: "lat", }, }) .shape("circle") .size(4) .active({ color: "#AE0F09", }) .color("#00AB3D") .style({ opacity: 1, stroke: "#fff", strokeWidth: 1, }); this.hpaas.l7Scene.addLayer(this.pointLayer); this.shapeLayer = new LineLayer({ zIndex: 1001, }) .source(featureCollection([])) .style({ lineType: "dash", dashArray: [2, 2], }) .size(2) .shape("line") .color("#00AB3D") .style({ opacity: 1, cursor: "pointer", }); this.hpaas.l7Scene.addLayer(this.shapeLayer); this.popup = new Popup({ // offsets: [iconSize / 2, 0], closeButton: false, stopPropagation: false, anchor: "bottom", }).setLnglat({ lng: 0, lat: 0 }); } /** * 事件绑定,解绑等 */ private mouseClickHandler = (e: any) => { if (e) { const point = e.lnglat ?? (e.lngLat as GeoPoint); // const point = e.lnglat || (e.lngLat as GeoPoint); this.drawingPoints.push(point); } this.render(); }; private mouseDblClickHandler = () => { this.save(); }; private mouseMoveHandler = (e: any) => { if (e) { const point = e.lnglat ?? (e.lngLat as GeoPoint); const { lng, lat } = point; this.movingPoint = point; this.hpaas.l7Scene.addPopup(this.popup); if (this.drawingPoints.length == 0) { this.popup.setHTML( `
点击开始绘制切分线
🖱双击停止绘制并切分
` ); this.popup.setLnglat([lng, lat]).open(); } else { this.popup.setHTML(`
🖱双击停止绘制
`); this.popup.setLnglat([lng, lat]).open(); } } this.render(); }; private handleEvent(type: "off" | "on" = "on") { this.hpaas.l7Scene.setMapStatus({ doubleClickZoom: type === "off", }); this.hpaas.l7Scene[type]("click", this.mouseClickHandler); this.hpaas.l7Scene[type]("dblclick", this.mouseDblClickHandler); this.hpaas.l7Scene[type]("mousemove", this.mouseMoveHandler); } private render() { /** * 渲染点 */ const points = this.drawingPoints.concat([this.movingPoint]); this.pointLayer.setData(points); /** * 渲染线 */ const lineCollection = featureCollection([]); if (points.length >= 2) { const _lineString = lineString(points.map(({ lng, lat }) => [lng, lat])); lineCollection.features = lineCollection.features.concat(_lineString); this.shapeLayer.setData(lineCollection); // 当只有一个点的时候,就不去渲染线 } else { this.shapeLayer.setData(lineCollection); } } begin(features: PolygonFeatureType) { if (this.isSplitting) { return; } this.splittingFeature = features; this.isSplitting = true; this.handleEvent(); } end() { this.isSplitting = false; this.movingPoint = { lat: 0, lng: 0 }; this.popup.close(); // 去掉绘制断线过程中的事件 this.handleEvent("off"); this.off("SAVE_SPLIT"); } clear() { this.drawingPoints = []; this.end(); this.render(); } save() { const line = lineString( this.drawingPoints.map((point) => { return [point.lng, point.lat]; }) ); const segmentFeatures: PolygonFeatureType[] = []; const res = splitMultiPolygonByLine(this.splittingFeature, line); if (res) { segmentFeatures.push(res as PolygonFeatureType); } this.emit("SAVE_SPLIT", segmentFeatures); this.clear(); } } export default LineSplit;