From ead9ac685ef69e90e46c2ca959105ee8152c5908 Mon Sep 17 00:00:00 2001 From: Cmen <1176967590@qq.com> Date: Fri, 4 Mar 2022 09:57:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=AF=BC=E5=85=A5=E5=B7=A5?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/map/editors/BaseOverlayEditor.ts | 3 ++ src/map/editors/CircleEditor.ts | 18 ++++++++-- src/map/editors/PolygonEditor.ts | 16 +++++++-- src/map/editors/PolylineEditor.ts | 9 +++++ src/map/editors/RectangleEditor.ts | 29 +++++++++++++++ src/map/index.ts | 54 +++++++++++++++++++++++++--- src/store/GlobalController.ts | 19 +++++----- src/store/reducers/index.ts | 6 +++- 8 files changed, 135 insertions(+), 19 deletions(-) diff --git a/src/map/editors/BaseOverlayEditor.ts b/src/map/editors/BaseOverlayEditor.ts index 9190650..e44a1f6 100644 --- a/src/map/editors/BaseOverlayEditor.ts +++ b/src/map/editors/BaseOverlayEditor.ts @@ -1,4 +1,5 @@ import { OverlayTypes } from "@types"; +import { IOverlay } from "../../store/type"; export abstract class BaseOverlayEditor { map: AMap.Map; @@ -28,5 +29,7 @@ export abstract class BaseOverlayEditor { this.editor.open(); } + abstract build(overlay: IOverlay): AMap.MapOverlay; + abstract getType(): OverlayTypes; } diff --git a/src/map/editors/CircleEditor.ts b/src/map/editors/CircleEditor.ts index 8265170..193aa7a 100644 --- a/src/map/editors/CircleEditor.ts +++ b/src/map/editors/CircleEditor.ts @@ -1,11 +1,23 @@ import { OverlayTypes } from "@types"; +import { IOverlay } from "@store"; import { BaseOverlayEditor } from "./BaseOverlayEditor"; export class CircleEditor extends BaseOverlayEditor { - getType(): OverlayTypes { - return OverlayTypes.Circle; - } initEditor(map: AMap.Map) { return new AMap.CircleEditor(this.map); } + + build(circle: IOverlay): AMap.MapOverlay { + const { lngLat, radius } = circle; + const [lng, lat] = lngLat!; + const circleOverlay = new AMap.Circle({ + center: new AMap.LngLat(lng, lat), + radius: radius!, + }); + return circleOverlay; + } + + getType(): OverlayTypes { + return OverlayTypes.Circle; + } } diff --git a/src/map/editors/PolygonEditor.ts b/src/map/editors/PolygonEditor.ts index 2962c8d..89e461d 100644 --- a/src/map/editors/PolygonEditor.ts +++ b/src/map/editors/PolygonEditor.ts @@ -1,11 +1,21 @@ import { OverlayTypes } from "@types"; +import { IOverlay } from "../../store/type"; import { BaseOverlayEditor } from "./BaseOverlayEditor"; export class PolygonEditor extends BaseOverlayEditor { - getType(): OverlayTypes { - return OverlayTypes.Polygon; - } initEditor(map: AMap.Map) { return new AMap.PolygonEditor(map); } + + build(polygon: IOverlay): AMap.MapOverlay { + const { path } = polygon; + const polygonOverlay = new AMap.Polygon({ + path: (path || []).map(([lng, lat]) => new AMap.LngLat(lng, lat)), + }); + return polygonOverlay; + } + + getType(): OverlayTypes { + return OverlayTypes.Polygon; + } } diff --git a/src/map/editors/PolylineEditor.ts b/src/map/editors/PolylineEditor.ts index 7b340cc..538ca1f 100644 --- a/src/map/editors/PolylineEditor.ts +++ b/src/map/editors/PolylineEditor.ts @@ -1,4 +1,5 @@ import { OverlayTypes } from "@types"; +import { IOverlay } from "@store"; import { BaseOverlayEditor } from "./BaseOverlayEditor"; export class PolylineEditor extends BaseOverlayEditor { @@ -6,6 +7,14 @@ export class PolylineEditor extends BaseOverlayEditor { return new AMap.PolylineEditor(this.map); } + build(polyline: IOverlay): AMap.MapOverlay { + const { path } = polyline; + const polylineOverlay = new AMap.Polyline({ + path: (path || []).map(([lng, lat]) => new AMap.LngLat(lng, lat)), + }); + return polylineOverlay; + } + getType(): OverlayTypes { return OverlayTypes.Polyline; } diff --git a/src/map/editors/RectangleEditor.ts b/src/map/editors/RectangleEditor.ts index ca66ebd..5d2fd92 100644 --- a/src/map/editors/RectangleEditor.ts +++ b/src/map/editors/RectangleEditor.ts @@ -1,4 +1,5 @@ import { OverlayTypes } from "@types"; +import { IOverlay } from "../../store/type"; import { BaseOverlayEditor } from "./BaseOverlayEditor"; export class RectangleEditor extends BaseOverlayEditor { @@ -20,6 +21,34 @@ export class RectangleEditor extends BaseOverlayEditor { return target; } + build(rect: IOverlay): AMap.MapOverlay { + const { path } = rect; + let west = 180, + east = -180, + north = -90, + south = 90; + path?.forEach((position) => { + const [lng, lat] = position; + west = Math.min(lng, west); + east = Math.max(lng, east); + north = Math.max(lat, north); + south = Math.min(lat, south); + }); + const bounds = new AMap.Bounds( + new AMap.LngLat(west, south), + new AMap.LngLat(east, north) + ); + console.log(bounds); + const rectOverlay = new AMap.Rectangle({ + bounds, + fillOpacity: 0.1, + bubble: true, + cursor: "pointer", + strokeColor: "#f00", + }); + return rectOverlay; + } + getType(): OverlayTypes { return OverlayTypes.Rectangle; } diff --git a/src/map/index.ts b/src/map/index.ts index 9ebb1ed..884aa81 100644 --- a/src/map/index.ts +++ b/src/map/index.ts @@ -1,7 +1,7 @@ import Emitter from "@finevis/emitter"; import "@amap/amap-jsapi-types"; -import { IMapState } from "@store"; +import { IMapState, IOverlay } from "@store"; import { getOverlayPaths, getUID } from "@utils"; import { @@ -84,6 +84,10 @@ export class MapEditor extends Emitter { break; case Command.DeleteOverlays: this._deleteOverlays(); + break; + case Command.OpenProject: + this.importOverlays(mapState); + break; } } @@ -103,13 +107,54 @@ export class MapEditor extends Emitter { ); } - importOverlays() { - // + importOverlays(mapState: IMapState) { + this.clearOverlays(); + const { rectangles, polygons, polylines, circles } = mapState; + const rectangleEditor = this.getEditorByType(OverlayTypes.Rectangle); + const polygonEditor = this.getEditorByType(OverlayTypes.Polygon); + const polylineEditor = this.getEditorByType(OverlayTypes.Polyline); + const circleEditor = this.getEditorByType(OverlayTypes.Circle); + + const addOverlay = ( + id: string, + target: AMap.MapOverlay, + type: OverlayTypes + ) => { + this.overlayMap[id] = { + type, + target, + }; + this.map.add(target); + }; + + rectangles.forEach((rect) => + addOverlay(rect.id, rectangleEditor!.build(rect), OverlayTypes.Rectangle) + ); + polygons.forEach((polygon) => + addOverlay( + polygon.id, + polygonEditor!.build(polygon), + OverlayTypes.Polygon + ) + ); + polylines.forEach((polyline) => + addOverlay( + polyline.id, + polylineEditor!.build(polyline), + OverlayTypes.Polyline + ) + ); + circles.forEach((circle) => + addOverlay(circle.id, circleEditor!.build(circle), OverlayTypes.Circle) + ); } // 清空所有覆盖物 clearOverlays() { - // + for (let id in this.overlayMap) { + this.map.remove(this.overlayMap[id].target); + } + this.overlayMap = {}; } _createOverlay(mapState: IMapState) { @@ -133,6 +178,7 @@ export class MapEditor extends Emitter { this._selectedIds.forEach((id) => { const { target } = this.overlayMap[id]; this.map.remove(target); + delete this.overlayMap[id]; }); } diff --git a/src/store/GlobalController.ts b/src/store/GlobalController.ts index 2d8c2b8..bead52f 100644 --- a/src/store/GlobalController.ts +++ b/src/store/GlobalController.ts @@ -23,29 +23,32 @@ interface IGlobalController { // 全局控制器, 用以复用一些快捷方法. export class GlobelController implements IGlobalController { - _store: IStore; + store: IStore; + constructor(store: IStore) { - this._store = store; + this.store = store; this._bindOperations(); this._registerHotkeys(); const cached = sessionStorage.getItem("fine-geojson"); if (cached != null) { - this._replaceState(JSON.parse(cached)); + setTimeout(() => { + this._replaceState(JSON.parse(cached)); + }, 3000); } setInterval(() => { sessionStorage.setItem( "fine-geojson", - JSON.stringify(this._store.getState()) + JSON.stringify(this.store.getState()) ); console.log("updated!"); }, 10000); } get mapState() { - return this._store.getState().map; + return this.store.getState().map; } saveGeoJSON() { @@ -85,7 +88,7 @@ export class GlobelController implements IGlobalController { } createOverlay(type: OverlayTypes) { - this._store.dispatch(EditorAction.createOverlay(type)); + this.store.dispatch(EditorAction.createOverlay(type)); } deleteOverlays() { @@ -94,13 +97,13 @@ export class GlobelController implements IGlobalController { Modal.confirm({ title: "确定删除覆盖物吗?", onOk: () => { - this._store.dispatch(EditorAction.deleteOverlays()); + this.store.dispatch(EditorAction.deleteOverlays()); }, }); } private _replaceState(state: IEditorState) { - this._store.dispatch(EditorAction.replaceState(state)); + this.store.dispatch(EditorAction.replaceState(state)); } private _bindOperations() { diff --git a/src/store/reducers/index.ts b/src/store/reducers/index.ts index c18c756..f88ed64 100644 --- a/src/store/reducers/index.ts +++ b/src/store/reducers/index.ts @@ -1,3 +1,4 @@ +import produce from "immer"; import { IEditorState } from "../type"; import { initState } from "../initState"; import { ActionTypes } from "../actions"; @@ -7,6 +8,7 @@ import { selectOverlay, deleteOverlays, } from "./map"; +import { Command } from "@types"; export type Action = { type: ActionTypes; @@ -24,7 +26,9 @@ const actionReducers: Record = { }; function replaceState(state = initState, payload: IEditorState) { - return payload; + return produce(payload, (draft) => { + draft.map.command = Command.OpenProject; + }); } export function reducer(state = initState, action: Action) {