diff --git a/src/editor/Plot/mapHooks.ts b/src/editor/Plot/mapHooks.ts index 1fed897..8c6f493 100644 --- a/src/editor/Plot/mapHooks.ts +++ b/src/editor/Plot/mapHooks.ts @@ -1,12 +1,12 @@ import { Dispatch } from "react"; -import { EditorAction, IEditorState } from "@store"; +import { EditorAction } from "@store"; import { MapEditor } from "@map"; import { EventTypes } from "../../types/enum"; // 注册地图的事件钩子 export function registerMapEventHooks(map: MapEditor, dispatch: Dispatch) { // - map.on(EventTypes.FinishCreateOverlay, (evt: any) => - dispatch(EditorAction.finishCreateOverlay(evt)) + map.on(EventTypes.FinishEditOverlay, (evt: any) => + dispatch(EditorAction.finishEditOverlay(evt)) ); } diff --git a/src/map/editors/BaseOverlayEditor.ts b/src/map/editors/BaseOverlayEditor.ts index 45bccde..9190650 100644 --- a/src/map/editors/BaseOverlayEditor.ts +++ b/src/map/editors/BaseOverlayEditor.ts @@ -23,5 +23,10 @@ export abstract class BaseOverlayEditor { return target; } + edit(target: AMap.MapOverlay) { + this.editor.setTarget(target); + this.editor.open(); + } + abstract getType(): OverlayTypes; } diff --git a/src/map/index.ts b/src/map/index.ts index 0d429c8..2d1ffc9 100644 --- a/src/map/index.ts +++ b/src/map/index.ts @@ -18,7 +18,7 @@ import { PolygonOptions, PolylineOptions, SelectedOptions } from "./constants"; import { Command, EventTypes, OverlayTypes } from "../types/enum"; let uuid = 0; -const getUuid = () => ++uuid; +const getUuid = () => ++uuid + ""; type AMapOverlayEditor = | AMap.RectangleEditor @@ -39,6 +39,8 @@ export class MapEditor extends Emitter { private _currentOverlayEditor: | BaseOverlayEditor | undefined; + private _selectedIds: string[] = []; + private _editorStatus: "editing" | "creating" | null = null; constructor(dom: HTMLDivElement) { super(); this.dom = dom; @@ -64,10 +66,17 @@ export class MapEditor extends Emitter { this._map = new AMap.Map(this.dom); this.initEditors(); // Space的key是空字符串, 这就离谱. - registerHotkey(" ", { callback: this.finishCreateOverlay.bind(this) }); + 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: @@ -78,30 +87,50 @@ export class MapEditor extends Emitter { } } - _createOverlay(mapState: IMapState) { - const { overlayType } = mapState; - this.finishCreateOverlay(); - this._currentOverlayEditor = this.overlayEditors.find( + 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 ); + } + + _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); }); } - finishCreateOverlay() { + _finishEditOverlay() { 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 isCreatingOverlay = this._editorStatus === "creating"; + let id = getUuid(); + 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; @@ -113,16 +142,16 @@ export class MapEditor extends Emitter { target.setOptions( type === OverlayTypes.Polyline ? PolylineOptions : PolygonOptions ); - this.emit(EventTypes.FinishCreateOverlay, evt); + this.emit(EventTypes.FinishEditOverlay, evt); + this._editorStatus = null; } - initEditors() { - const { map } = this; - this.overlayEditors = [ - new RectangleEditor(map), - new PolygonEditor(map), - new PolylineEditor(map), - new CircleEditor(map), - ]; + _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"; } } diff --git a/src/store/actions.ts b/src/store/actions.ts index 1195b49..22d609e 100644 --- a/src/store/actions.ts +++ b/src/store/actions.ts @@ -3,7 +3,7 @@ import { OverlayTypes } from "@types"; export enum ActionTypes { // AddRect = "addRect", CreateOverlay = "createOverlay", - FinishCreateOverlay = "finishCreateOverlay", + FinishEditOverlay = "finishEditOverlay", SelectOverlay = "selectOverlay", } @@ -21,9 +21,9 @@ export const EditorAction: Record = { payload: type, }; }, - finishCreateOverlay(overlay: any) { + finishEditOverlay(overlay: any) { return { - type: ActionTypes.FinishCreateOverlay, + type: ActionTypes.FinishEditOverlay, payload: overlay as CreatedOverlay, }; }, diff --git a/src/store/reducers/index.ts b/src/store/reducers/index.ts index d9c3543..540b992 100644 --- a/src/store/reducers/index.ts +++ b/src/store/reducers/index.ts @@ -1,6 +1,6 @@ import { initState } from "../initState"; import { ActionTypes } from "../actions"; -import { createOverlay, finishCreateOverlay, selectOverlay } from "./map"; +import { createOverlay, finishEditOverlay, selectOverlay } from "./map"; import { IEditorState } from "@store"; export type Action = { @@ -12,7 +12,7 @@ type ActionReducer = (state: IEditorState, payload: any) => IEditorState; const actionReducers: Record = { [ActionTypes.CreateOverlay]: createOverlay, - [ActionTypes.FinishCreateOverlay]: finishCreateOverlay, + [ActionTypes.FinishEditOverlay]: finishEditOverlay, [ActionTypes.SelectOverlay]: selectOverlay, // addRect: undefined }; diff --git a/src/store/reducers/map/index.ts b/src/store/reducers/map/index.ts index 53ef093..d2378c6 100644 --- a/src/store/reducers/map/index.ts +++ b/src/store/reducers/map/index.ts @@ -11,23 +11,29 @@ export function createOverlay(state = initState, payload: any) { }); } -export function finishCreateOverlay(state = initState, payload: any) { +export function finishEditOverlay(state = initState, payload: any) { return produce(state, (draft) => { const overlay = payload as IOverlay; - const { type } = overlay; + const { type, id } = overlay; // todo: uniqueName. overlay.name = OverlayNamePrefixs[type] + overlay.id; draft.map.status = null; draft.map.command = null; draft.map.overlayType = null; - (type === OverlayTypes.Rectangle - ? draft.map.rectangles - : type === OverlayTypes.Circle - ? draft.map.circles - : type === OverlayTypes.Polygon - ? draft.map.polygons - : draft.map.polylines - ).push(overlay); + const overlays = + type === OverlayTypes.Rectangle + ? draft.map.rectangles + : type === OverlayTypes.Circle + ? draft.map.circles + : type === OverlayTypes.Polygon + ? draft.map.polygons + : draft.map.polylines; + const existed = overlays.find((overlay) => overlay.id === id); + if (existed) { + overlays[overlays.indexOf(existed)] = overlay; + } else { + overlays.push(overlay); + } }); } diff --git a/src/types/enum.ts b/src/types/enum.ts index 3ac0f55..0041df4 100644 --- a/src/types/enum.ts +++ b/src/types/enum.ts @@ -1,5 +1,5 @@ export enum EventTypes { - FinishCreateOverlay = "finishCreateOverlay", + FinishEditOverlay = "finishEditOverlay", } export enum OverlayTypes {