基于高德地图JS api开发的geojson编辑器. http://geojson.finevis.cc/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

175 lines
4.5 KiB

import Emitter from "@finevis/emitter";
import "@amap/amap-jsapi-types";
import { IMapState } from "@store";
import { getOverlayPaths, getUID } 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";
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;
private _selectedIds: string[] = [];
private _editorStatus: "editing" | "creating" | null = null;
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._finishEditOverlay.bind(this) });
registerHotkey("e", {
callback: this._editSelectedOverlay.bind(this),
alt: true,
});
}
update(mapState: IMapState) {
if (this._editorStatus != null) {
this._finishEditOverlay();
}
const { command } = mapState;
switch (command) {
case Command.CreateOverlay:
this._createOverlay(mapState);
break;
case Command.SelectOverlay:
this._selectOverlays(mapState.selectedIds);
break;
case Command.DeleteOverlays:
this._deleteOverlays();
}
}
initEditors() {
const { map } = this;
this.overlayEditors = [
new RectangleEditor(map),
new PolygonEditor(map),
new PolylineEditor(map),
new CircleEditor(map),
];
}
getEditorByType(overlayType: OverlayTypes) {
return this.overlayEditors.find(
(editor) => editor.getType() === overlayType
);
}
importOverlays() {
//
}
// 清空所有覆盖物
clearOverlays() {
//
}
_createOverlay(mapState: IMapState) {
const { overlayType } = mapState;
this._currentOverlayEditor = this.getEditorByType(overlayType!);
this._currentOverlayEditor?.create();
this._editorStatus = "creating";
}
_selectOverlays(ids?: string[]) {
if (!ids?.length) return;
this._selectedIds = ids;
ids.forEach((id) => {
const { target } = this.overlayMap[id];
target.setOptions(SelectedOptions);
});
}
_deleteOverlays() {
if (this._selectedIds?.length === 0) return;
this._selectedIds.forEach((id) => {
const { target } = this.overlayMap[id];
this.map.remove(target);
});
}
_finishEditOverlay() {
if (this._currentOverlayEditor == null) return;
const target = this._currentOverlayEditor.finish();
if (target == null) return;
const type = this._currentOverlayEditor.getType();
const isCreatingOverlay = this._editorStatus === "creating";
let id = getUID();
if (isCreatingOverlay) {
this.overlayMap[id] = { type, target };
} else {
id = this._selectedIds[0];
}
const evt: any = { id, type };
if (type === OverlayTypes.Circle) {
const circle = target as AMap.Circle;
const { lng, lat } = circle.getCenter();
evt.lngLat = [lng, lat];
evt.radius = circle.getRadius();
} else {
evt.path = getOverlayPaths(target, type);
}
target.setOptions(
type === OverlayTypes.Polyline ? PolylineOptions : PolygonOptions
);
this.emit(EventTypes.FinishEditOverlay, evt);
this._editorStatus = null;
}
_editSelectedOverlay() {
if (this._selectedIds.length !== 1) return;
const [id] = this._selectedIds;
const { target, type } = this.overlayMap[id];
this._currentOverlayEditor = this.getEditorByType(type);
this._currentOverlayEditor?.edit(target);
this._editorStatus = "editing";
}
}