import Emitter from "@finevis/emitter"; import "@amap/amap-jsapi-types"; import { IMapState } from "@store"; import { getOverlayPaths } from "@utils"; import { BaseOverlayEditor, RectangleEditor, PolygonEditor, PolylineEditor, CircleEditor, } from "./editors"; import { registerHotkey } from "../utils/hotkeys"; import { PolygonOptions, PolylineOptions, SelectedOptions } from "./constants"; import { Command, EventTypes, OverlayTypes } from "../types/enum"; let uuid = 0; const getUuid = () => ++uuid; type AMapOverlayEditor = | AMap.RectangleEditor | AMap.PolygonEditor | AMap.PolylineEditor | AMap.CircleEditor; type OverlayTemp = { type: OverlayTypes; target: AMap.MapOverlay; }; export class MapEditor extends Emitter { dom: HTMLDivElement; private _map: AMap.Map | undefined; private overlayEditors: BaseOverlayEditor[] = []; private overlayMap: Record = {}; private _currentOverlayEditor: | BaseOverlayEditor | undefined; constructor(dom: HTMLDivElement) { super(); this.dom = dom; } get map() { return this._map!; } async init() { await AMapLoader.load({ key: "a4171ad2d7df42823b4de7d25c8c35ee", version: "2.0", plugins: [ "AMap.RectangleEditor", "AMap.PolylineEditor", "AMap.PolygonEditor", "AMap.CircleEditor", "AMap.PlaceSearch", "AMap.AutoComplete", ], }); this._map = new AMap.Map(this.dom); this.initEditors(); // Space的key是空字符串, 这就离谱. registerHotkey(" ", { callback: this.finishCreateOverlay.bind(this) }); } update(mapState: IMapState) { const { command } = mapState; switch (command) { case Command.CreateOverlay: this._createOverlay(mapState); break; case Command.SelectOverlay: this._selectOverlays(mapState.selectedIds); } } _createOverlay(mapState: IMapState) { const { overlayType } = mapState; this.finishCreateOverlay(); this._currentOverlayEditor = this.overlayEditors.find( (editor) => editor.getType() === overlayType ); this._currentOverlayEditor?.create(); } _selectOverlays(ids?: string[]) { if (!ids?.length) return; ids.forEach((id) => { const { target } = this.overlayMap[id]; target.setOptions(SelectedOptions); }); } finishCreateOverlay() { if (this._currentOverlayEditor == null) return; const target = this._currentOverlayEditor.finish(); if (target == null) return; const id = getUuid(); const type = this._currentOverlayEditor.getType(); this.overlayMap[id] = { type, target }; const evt: any = { id, type }; if (type === OverlayTypes.Circle) { const circle = target as AMap.Circle; evt.lngLat = circle.getCenter(); evt.radius = circle.getRadius(); } else { evt.path = getOverlayPaths(target, type); } target.setOptions( type === OverlayTypes.Polyline ? PolylineOptions : PolygonOptions ); this.emit(EventTypes.FinishCreateOverlay, evt); } initEditors() { const { map } = this; this.overlayEditors = [ new RectangleEditor(map), new PolygonEditor(map), new PolylineEditor(map), new CircleEditor(map), ]; } }