Browse Source

选择编辑

master
Cmen 3 years ago
parent
commit
e459b73a23
  1. 6
      src/editor/Plot/mapHooks.ts
  2. 5
      src/map/editors/BaseOverlayEditor.ts
  3. 63
      src/map/index.ts
  4. 6
      src/store/actions.ts
  5. 4
      src/store/reducers/index.ts
  6. 16
      src/store/reducers/map/index.ts
  7. 2
      src/types/enum.ts

6
src/editor/Plot/mapHooks.ts

@ -1,12 +1,12 @@
import { Dispatch } from "react"; import { Dispatch } from "react";
import { EditorAction, IEditorState } from "@store"; import { EditorAction } from "@store";
import { MapEditor } from "@map"; import { MapEditor } from "@map";
import { EventTypes } from "../../types/enum"; import { EventTypes } from "../../types/enum";
// 注册地图的事件钩子 // 注册地图的事件钩子
export function registerMapEventHooks(map: MapEditor, dispatch: Dispatch<any>) { export function registerMapEventHooks(map: MapEditor, dispatch: Dispatch<any>) {
// //
map.on(EventTypes.FinishCreateOverlay, (evt: any) => map.on(EventTypes.FinishEditOverlay, (evt: any) =>
dispatch(EditorAction.finishCreateOverlay(evt)) dispatch(EditorAction.finishEditOverlay(evt))
); );
} }

5
src/map/editors/BaseOverlayEditor.ts

@ -23,5 +23,10 @@ export abstract class BaseOverlayEditor<T extends AMap.BaseEditor> {
return target; return target;
} }
edit(target: AMap.MapOverlay) {
this.editor.setTarget(target);
this.editor.open();
}
abstract getType(): OverlayTypes; abstract getType(): OverlayTypes;
} }

63
src/map/index.ts

@ -18,7 +18,7 @@ import { PolygonOptions, PolylineOptions, SelectedOptions } from "./constants";
import { Command, EventTypes, OverlayTypes } from "../types/enum"; import { Command, EventTypes, OverlayTypes } from "../types/enum";
let uuid = 0; let uuid = 0;
const getUuid = () => ++uuid; const getUuid = () => ++uuid + "";
type AMapOverlayEditor = type AMapOverlayEditor =
| AMap.RectangleEditor | AMap.RectangleEditor
@ -39,6 +39,8 @@ export class MapEditor extends Emitter {
private _currentOverlayEditor: private _currentOverlayEditor:
| BaseOverlayEditor<AMapOverlayEditor> | BaseOverlayEditor<AMapOverlayEditor>
| undefined; | undefined;
private _selectedIds: string[] = [];
private _editorStatus: "editing" | "creating" | null = null;
constructor(dom: HTMLDivElement) { constructor(dom: HTMLDivElement) {
super(); super();
this.dom = dom; this.dom = dom;
@ -64,10 +66,17 @@ export class MapEditor extends Emitter {
this._map = new AMap.Map(this.dom); this._map = new AMap.Map(this.dom);
this.initEditors(); this.initEditors();
// Space的key是空字符串, 这就离谱. // 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) { update(mapState: IMapState) {
if (this._editorStatus != null) {
this._finishEditOverlay();
}
const { command } = mapState; const { command } = mapState;
switch (command) { switch (command) {
case Command.CreateOverlay: case Command.CreateOverlay:
@ -78,30 +87,50 @@ export class MapEditor extends Emitter {
} }
} }
_createOverlay(mapState: IMapState) { initEditors() {
const { overlayType } = mapState; const { map } = this;
this.finishCreateOverlay(); this.overlayEditors = [
this._currentOverlayEditor = this.overlayEditors.find( new RectangleEditor(map),
new PolygonEditor(map),
new PolylineEditor(map),
new CircleEditor(map),
];
}
getEditorByType(overlayType: OverlayTypes) {
return this.overlayEditors.find(
(editor) => editor.getType() === overlayType (editor) => editor.getType() === overlayType
); );
}
_createOverlay(mapState: IMapState) {
const { overlayType } = mapState;
this._currentOverlayEditor = this.getEditorByType(overlayType!);
this._currentOverlayEditor?.create(); this._currentOverlayEditor?.create();
this._editorStatus = "creating";
} }
_selectOverlays(ids?: string[]) { _selectOverlays(ids?: string[]) {
if (!ids?.length) return; if (!ids?.length) return;
this._selectedIds = ids;
ids.forEach((id) => { ids.forEach((id) => {
const { target } = this.overlayMap[id]; const { target } = this.overlayMap[id];
target.setOptions(SelectedOptions); target.setOptions(SelectedOptions);
}); });
} }
finishCreateOverlay() { _finishEditOverlay() {
if (this._currentOverlayEditor == null) return; if (this._currentOverlayEditor == null) return;
const target = this._currentOverlayEditor.finish(); const target = this._currentOverlayEditor.finish();
if (target == null) return; if (target == null) return;
const id = getUuid();
const type = this._currentOverlayEditor.getType(); const type = this._currentOverlayEditor.getType();
const isCreatingOverlay = this._editorStatus === "creating";
let id = getUuid();
if (isCreatingOverlay) {
this.overlayMap[id] = { type, target }; this.overlayMap[id] = { type, target };
} else {
id = this._selectedIds[0];
}
const evt: any = { id, type }; const evt: any = { id, type };
if (type === OverlayTypes.Circle) { if (type === OverlayTypes.Circle) {
const circle = target as AMap.Circle; const circle = target as AMap.Circle;
@ -113,16 +142,16 @@ export class MapEditor extends Emitter {
target.setOptions( target.setOptions(
type === OverlayTypes.Polyline ? PolylineOptions : PolygonOptions type === OverlayTypes.Polyline ? PolylineOptions : PolygonOptions
); );
this.emit(EventTypes.FinishCreateOverlay, evt); this.emit(EventTypes.FinishEditOverlay, evt);
this._editorStatus = null;
} }
initEditors() { _editSelectedOverlay() {
const { map } = this; if (this._selectedIds.length !== 1) return;
this.overlayEditors = [ const [id] = this._selectedIds;
new RectangleEditor(map), const { target, type } = this.overlayMap[id];
new PolygonEditor(map), this._currentOverlayEditor = this.getEditorByType(type);
new PolylineEditor(map), this._currentOverlayEditor?.edit(target);
new CircleEditor(map), this._editorStatus = "editing";
];
} }
} }

6
src/store/actions.ts

@ -3,7 +3,7 @@ import { OverlayTypes } from "@types";
export enum ActionTypes { export enum ActionTypes {
// AddRect = "addRect", // AddRect = "addRect",
CreateOverlay = "createOverlay", CreateOverlay = "createOverlay",
FinishCreateOverlay = "finishCreateOverlay", FinishEditOverlay = "finishEditOverlay",
SelectOverlay = "selectOverlay", SelectOverlay = "selectOverlay",
} }
@ -21,9 +21,9 @@ export const EditorAction: Record<ActionTypes, ActionCreator> = {
payload: type, payload: type,
}; };
}, },
finishCreateOverlay(overlay: any) { finishEditOverlay(overlay: any) {
return { return {
type: ActionTypes.FinishCreateOverlay, type: ActionTypes.FinishEditOverlay,
payload: overlay as CreatedOverlay, payload: overlay as CreatedOverlay,
}; };
}, },

4
src/store/reducers/index.ts

@ -1,6 +1,6 @@
import { initState } from "../initState"; import { initState } from "../initState";
import { ActionTypes } from "../actions"; import { ActionTypes } from "../actions";
import { createOverlay, finishCreateOverlay, selectOverlay } from "./map"; import { createOverlay, finishEditOverlay, selectOverlay } from "./map";
import { IEditorState } from "@store"; import { IEditorState } from "@store";
export type Action = { export type Action = {
@ -12,7 +12,7 @@ type ActionReducer = (state: IEditorState, payload: any) => IEditorState;
const actionReducers: Record<ActionTypes, ActionReducer> = { const actionReducers: Record<ActionTypes, ActionReducer> = {
[ActionTypes.CreateOverlay]: createOverlay, [ActionTypes.CreateOverlay]: createOverlay,
[ActionTypes.FinishCreateOverlay]: finishCreateOverlay, [ActionTypes.FinishEditOverlay]: finishEditOverlay,
[ActionTypes.SelectOverlay]: selectOverlay, [ActionTypes.SelectOverlay]: selectOverlay,
// addRect: undefined // addRect: undefined
}; };

16
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) => { return produce(state, (draft) => {
const overlay = payload as IOverlay; const overlay = payload as IOverlay;
const { type } = overlay; const { type, id } = overlay;
// todo: uniqueName. // todo: uniqueName.
overlay.name = OverlayNamePrefixs[type] + overlay.id; overlay.name = OverlayNamePrefixs[type] + overlay.id;
draft.map.status = null; draft.map.status = null;
draft.map.command = null; draft.map.command = null;
draft.map.overlayType = null; draft.map.overlayType = null;
(type === OverlayTypes.Rectangle const overlays =
type === OverlayTypes.Rectangle
? draft.map.rectangles ? draft.map.rectangles
: type === OverlayTypes.Circle : type === OverlayTypes.Circle
? draft.map.circles ? draft.map.circles
: type === OverlayTypes.Polygon : type === OverlayTypes.Polygon
? draft.map.polygons ? draft.map.polygons
: draft.map.polylines : draft.map.polylines;
).push(overlay); const existed = overlays.find((overlay) => overlay.id === id);
if (existed) {
overlays[overlays.indexOf(existed)] = overlay;
} else {
overlays.push(overlay);
}
}); });
} }

2
src/types/enum.ts

@ -1,5 +1,5 @@
export enum EventTypes { export enum EventTypes {
FinishCreateOverlay = "finishCreateOverlay", FinishEditOverlay = "finishEditOverlay",
} }
export enum OverlayTypes { export enum OverlayTypes {

Loading…
Cancel
Save