diff --git a/src/editor/Catalog/index.tsx b/src/editor/Catalog/index.tsx index d074312..c3f41e4 100644 --- a/src/editor/Catalog/index.tsx +++ b/src/editor/Catalog/index.tsx @@ -1,10 +1,10 @@ import { Collapse } from "antd"; -import { useSelector } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; -import { mapStateSelector } from "@store"; -import { IOverlay } from "@store"; +import { IOverlay, EditorAction, mapStateSelector } from "@store"; import "./style.less"; +import classNames from "classnames"; const { Panel } = Collapse; @@ -14,12 +14,21 @@ export type OverlayListProps = { const OverlayList = (props: OverlayListProps) => { const { overlays } = props; + const dispatch = useDispatch(); + + const onClick = (id: string) => () => + dispatch(EditorAction.selectOverlay(id)); + const { selectedIds } = useSelector(mapStateSelector); return ( <> {overlays.map((overlay, index) => { + const selected = selectedIds && selectedIds.indexOf(overlay.id) >= 0; + const className = classNames("overlay-item", { + "overlay-item-selected": selected, + }); return ( -
+
{overlay.name}
); diff --git a/src/editor/Catalog/style.less b/src/editor/Catalog/style.less index 2031058..fbdbc2d 100644 --- a/src/editor/Catalog/style.less +++ b/src/editor/Catalog/style.less @@ -10,7 +10,10 @@ .overlay-item{ margin-bottom: 4px; cursor: pointer; - &:hover, &[data-selected]{ - background-color: #f7fafc; + &:hover{ + background-color: #e5e6e7; } +} +.overlay-item-selected{ + background-color: #e5e6e7; } \ No newline at end of file diff --git a/src/editor/Plot/Tools/index.tsx b/src/editor/Plot/Tools/index.tsx index b2599f9..06ba310 100644 --- a/src/editor/Plot/Tools/index.tsx +++ b/src/editor/Plot/Tools/index.tsx @@ -1,7 +1,7 @@ import { Tooltip } from "antd"; import { useDispatch, useSelector } from "react-redux"; import classnames from "classnames"; -import { editorAction, OverlayNamePrefixs, mapStateSelector } from "@store"; +import { EditorAction, OverlayNamePrefixs, mapStateSelector } from "@store"; import { OverlayTypes } from "@types"; type IconWithTipProps = { @@ -43,7 +43,7 @@ const OverlayTool = (props: OverlayToolProps) => { const { overlayType } = useSelector(mapStateSelector); const selected = type === overlayType; - const onClick = () => dispatch(editorAction.createOverlay(type)); + const onClick = () => dispatch(EditorAction.createOverlay(type)); return ; }; diff --git a/src/editor/Plot/index.tsx b/src/editor/Plot/index.tsx index d454032..c7a5bb0 100644 --- a/src/editor/Plot/index.tsx +++ b/src/editor/Plot/index.tsx @@ -2,7 +2,7 @@ import { Layout } from "antd"; import { useEffect, useRef, useState } from "react"; import { useSelector, useDispatch } from "react-redux"; import { MapEditor } from "@map"; -import { editorAction, IEditorState } from "@store"; +import { IEditorState } from "@store"; import Tools from "./Tools"; import { registerMapEventHooks } from "./mapHooks"; diff --git a/src/editor/Plot/mapHooks.ts b/src/editor/Plot/mapHooks.ts index 1ff8113..1fed897 100644 --- a/src/editor/Plot/mapHooks.ts +++ b/src/editor/Plot/mapHooks.ts @@ -1,5 +1,5 @@ import { Dispatch } from "react"; -import { editorAction, IEditorState } from "@store"; +import { EditorAction, IEditorState } from "@store"; import { MapEditor } from "@map"; import { EventTypes } from "../../types/enum"; @@ -7,6 +7,6 @@ import { EventTypes } from "../../types/enum"; export function registerMapEventHooks(map: MapEditor, dispatch: Dispatch) { // map.on(EventTypes.FinishCreateOverlay, (evt: any) => - dispatch(editorAction.finishCreateOverlay(evt)) + dispatch(EditorAction.finishCreateOverlay(evt)) ); } diff --git a/src/map/constants.ts b/src/map/constants.ts index ccd4df1..81bbab1 100644 --- a/src/map/constants.ts +++ b/src/map/constants.ts @@ -26,3 +26,7 @@ export const PolylineOptions: OverlayOptions = { draggable: false, bubble: true, }; + +export const SelectedOptions: OverlayOptions = { + strokeColor: SelectedStroke, +}; diff --git a/src/map/index.ts b/src/map/index.ts index 5705ec6..0d429c8 100644 --- a/src/map/index.ts +++ b/src/map/index.ts @@ -13,9 +13,9 @@ import { } from "./editors"; import { registerHotkey } from "../utils/hotkeys"; -import { PolygonOptions, PolylineOptions } from "./constants"; +import { PolygonOptions, PolylineOptions, SelectedOptions } from "./constants"; -import { EventTypes, OverlayTypes } from "../types/enum"; +import { Command, EventTypes, OverlayTypes } from "../types/enum"; let uuid = 0; const getUuid = () => ++uuid; @@ -26,11 +26,16 @@ type AMapOverlayEditor = | 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 overlayMap: Record = {}; private _currentOverlayEditor: | BaseOverlayEditor | undefined; @@ -63,23 +68,40 @@ export class MapEditor extends Emitter { } update(mapState: IMapState) { - const { status, overlayType } = mapState; - if (status === "createOverlay") { - this.finishCreateOverlay(); - this._currentOverlayEditor = this.overlayEditors.find( - (editor) => editor.getType() === overlayType - ); - this._currentOverlayEditor?.create(); + 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] = target; + this.overlayMap[id] = { type, target }; const evt: any = { id, type }; if (type === OverlayTypes.Circle) { const circle = target as AMap.Circle; diff --git a/src/store/actions.ts b/src/store/actions.ts index f1e948e..1195b49 100644 --- a/src/store/actions.ts +++ b/src/store/actions.ts @@ -4,28 +4,33 @@ export enum ActionTypes { // AddRect = "addRect", CreateOverlay = "createOverlay", FinishCreateOverlay = "finishCreateOverlay", + SelectOverlay = "selectOverlay", } export type CreatedOverlay = { id: string; type: OverlayTypes; }; -export class EditorAction { - // addRect() { - // return { - // type: ActionTypes.AddRect, - // }; - // } + +type ActionCreator = (payload: any) => { type: ActionTypes; payload: any }; + +export const EditorAction: Record = { createOverlay(type: OverlayTypes) { return { type: ActionTypes.CreateOverlay, payload: type, }; - } + }, finishCreateOverlay(overlay: any) { return { type: ActionTypes.FinishCreateOverlay, payload: overlay as CreatedOverlay, }; - } -} + }, + selectOverlay(id: string) { + return { + type: ActionTypes.SelectOverlay, + payload: id, + }; + }, +}; diff --git a/src/store/index.ts b/src/store/index.ts index 5a16286..98f58b8 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -15,7 +15,7 @@ const store: IStore = createStore(reducer); export { store }; -export const editorAction = new EditorAction(); +export { EditorAction }; export const StoreContext = createContext( null diff --git a/src/store/initState.ts b/src/store/initState.ts index cfde017..2552d65 100644 --- a/src/store/initState.ts +++ b/src/store/initState.ts @@ -2,7 +2,8 @@ import { IEditorState } from "./type"; export const initState: IEditorState = { map: { - status: "", + status: null, + command: null, overlayType: null, polygons: [], polylines: [], diff --git a/src/store/reducers/index.ts b/src/store/reducers/index.ts index 1d236cf..d9c3543 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 } from "./map"; +import { createOverlay, finishCreateOverlay, selectOverlay } from "./map"; import { IEditorState } from "@store"; export type Action = { @@ -13,6 +13,7 @@ type ActionReducer = (state: IEditorState, payload: any) => IEditorState; const actionReducers: Record = { [ActionTypes.CreateOverlay]: createOverlay, [ActionTypes.FinishCreateOverlay]: finishCreateOverlay, + [ActionTypes.SelectOverlay]: selectOverlay, // addRect: undefined }; diff --git a/src/store/reducers/map/index.ts b/src/store/reducers/map/index.ts index c7d511c..53ef093 100644 --- a/src/store/reducers/map/index.ts +++ b/src/store/reducers/map/index.ts @@ -1,11 +1,12 @@ import produce from "immer"; import { initState } from "../../initState"; import { IOverlay, OverlayNamePrefixs } from "@store"; -import { OverlayTypes } from "@types"; +import { OverlayTypes, Status, Command } from "@types"; export function createOverlay(state = initState, payload: any) { return produce(state, (draft) => { - draft.map.status = "createOverlay"; + draft.map.status = Status.CreateOverlay; + draft.map.command = Command.CreateOverlay; draft.map.overlayType = payload as OverlayTypes; }); } @@ -16,7 +17,8 @@ export function finishCreateOverlay(state = initState, payload: any) { const { type } = overlay; // todo: uniqueName. overlay.name = OverlayNamePrefixs[type] + overlay.id; - draft.map.status = ""; + draft.map.status = null; + draft.map.command = null; draft.map.overlayType = null; (type === OverlayTypes.Rectangle ? draft.map.rectangles @@ -28,3 +30,12 @@ export function finishCreateOverlay(state = initState, payload: any) { ).push(overlay); }); } + +export function selectOverlay(state = initState, payload: any) { + const id = payload as string; + return produce(state, (draft) => { + draft.map.command = Command.SelectOverlay; + draft.map.selectedIds = [id]; + draft.map.status = null; + }); +} diff --git a/src/store/type.ts b/src/store/type.ts index d5ff051..fe4dbca 100644 --- a/src/store/type.ts +++ b/src/store/type.ts @@ -1,4 +1,4 @@ -import { OverlayTypes } from "@types"; +import { OverlayTypes, Status, Command } from "@types"; export interface IOverlay { id: string; @@ -8,14 +8,15 @@ export interface IOverlay { paths?: number[][]; radius?: number; } - export interface IMapState { - status: string; + status: Status | null; + command: Command | null; overlayType: OverlayTypes | null; polygons: IOverlay[]; polylines: IOverlay[]; circles: IOverlay[]; rectangles: IOverlay[]; + selectedIds?: string[]; } export interface IEditorState { diff --git a/src/types/enum.ts b/src/types/enum.ts index 75b3e5a..3ac0f55 100644 --- a/src/types/enum.ts +++ b/src/types/enum.ts @@ -8,3 +8,16 @@ export enum OverlayTypes { Polyline = "polyline", Circle = "circle", } + +// 操作指令集 +export enum Command { + CreateOverlay = "createOveraly", + SelectOverlay = "selectOverlay", +} + +// 地图状态. +export enum Status { + CreateOverlay = "createOverlay", + Searching = "searching", + Selecting = "selecing", +}