|
|
|
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<AMapOverlayEditor>[] = [];
|
|
|
|
private overlayMap: Record<string, OverlayTemp> = {};
|
|
|
|
private _currentOverlayEditor:
|
|
|
|
| BaseOverlayEditor<AMapOverlayEditor>
|
|
|
|
| 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),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
}
|