Browse Source

feat: 走通地图&redux更新逻辑

master
Cmen 3 years ago
parent
commit
987cbdb56c
  1. 1
      package.json
  2. 20
      src/editor/Plot/Tools/index.tsx
  3. 29
      src/editor/Plot/index.tsx
  4. 5
      src/index.tsx
  5. 15
      src/map/editors/BaseLayerEditor.ts
  6. 7
      src/map/editors/RectangleEditor.ts
  7. 2
      src/map/editors/index.ts
  8. 21
      src/map/index.ts
  9. 18
      src/store/actions.ts
  10. 13
      src/store/index.ts
  11. 2
      src/store/initState.ts
  12. 24
      src/store/reducers.ts
  13. 2
      src/store/type.ts
  14. 6
      src/types/index.d.ts
  15. 22
      src/types/index.ts
  16. 8
      tsconfig.json
  17. 9
      vite.config.js
  18. 9186
      yarn.lock

1
package.json

@ -14,6 +14,7 @@
"lodash": "^4.17.21",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.6",
"redux": "^4.1.2"
},
"devDependencies": {

20
src/editor/Plot/Tools/index.tsx

@ -1,24 +1,38 @@
import { Tooltip } from "antd";
import { useDispatch } from "react-redux";
import { editorAction } from "@store";
type IconWithTipProps = {
type: string;
text: string;
onClick?: () => void;
placement?: "top" | "right";
};
const IconWithTip = ({ type, text, placement = "top" }: IconWithTipProps) => {
const IconWithTip = ({
type,
text,
onClick = () => {},
placement = "top",
}: IconWithTipProps) => {
return (
<Tooltip title={text} placement={placement}>
<span className={`icon icon-${type}`}></span>
<span className={`icon icon-${type}`} onClick={onClick}></span>
</Tooltip>
);
};
const Tools = () => {
const dispatch = useDispatch();
const createOverlay = (type: string) => () =>
dispatch(editorAction.createOverlay(type));
const createRectangle = createOverlay("rect");
return (
<>
<div className="marker-tools">
<IconWithTip type="rect" text="矩形工具" />
<IconWithTip type="rect" text="矩形工具" onClick={createRectangle} />
<IconWithTip type="circle" text="圆形工具" />
</div>
<div className="common-tools">

29
src/editor/Plot/index.tsx

@ -1,19 +1,34 @@
import { Layout } from "antd";
import { useEffect, useRef } from "react";
import { MapStage } from "../../mapStage";
import { useEffect, useRef, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { MapEditor } from "@map";
import { editorAction, IEditorState } from "@store";
import Tools from "./Tools";
import "./index.less";
const mapStateSelector = (state: IEditorState) => state.map;
const { Header, Footer, Sider, Content } = Layout;
const Plot = () => {
const mapStageRef = useRef<HTMLDivElement>(null);
const mapState = useSelector(mapStateSelector);
const dispatch = useDispatch();
const [mapEditor, setMapEditor] = useState<MapEditor | null>(null);
// !mapEditor &&
useEffect(() => {
const map = new MapStage(mapStageRef.current!);
map.init();
});
if (mapEditor == null) {
const editor = new MapEditor(mapStageRef.current!);
setMapEditor(editor);
editor.init().then(() => {
editor.update(mapState);
});
}
}, [mapEditor, mapState]);
mapEditor?.update(mapState);
return (
<>
@ -26,4 +41,8 @@ const Plot = () => {
);
};
// const mapStateToProps = (state: IEditorState) => {
// return state.map;
// };
export default Plot;

5
src/index.tsx

@ -1,5 +1,6 @@
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import "antd/dist/antd.css";
@ -8,8 +9,8 @@ import { Editor } from "./editor";
import "./index.less";
ReactDOM.render(
<StoreContext.Provider value={store}>
<Provider store={store}>
<Editor />
</StoreContext.Provider>,
</Provider>,
document.getElementById("app")
);

15
src/map/editors/BaseLayerEditor.ts

@ -0,0 +1,15 @@
export abstract class BaseLayerEditor<T extends AMap.BaseEditor> {
map: AMap.Map;
editor: T;
constructor(map: AMap.Map) {
this.map = map;
this.editor = this.initEditor(map);
}
abstract initEditor(map: AMap.Map): T;
create() {
this.editor.setTarget(null);
this.editor.open();
}
}

7
src/map/editors/RectangleEditor.ts

@ -0,0 +1,7 @@
import { BaseLayerEditor } from "./BaseLayerEditor";
export class RectangleEditor extends BaseLayerEditor<AMap.PolygonEditor> {
initEditor(map: AMap.Map) {
return new AMap.RectangleEditor(this.map);
}
}

2
src/map/editors/index.ts

@ -0,0 +1,2 @@
export * from "./BaseLayerEditor";
export * from "./RectangleEditor";

21
src/mapStage/index.ts → src/map/index.ts

@ -1,15 +1,18 @@
import "@amap/amap-jsapi-types";
import "../types/index.d";
import "../types";
import { IMapState } from "@store";
import { RectangleEditor } from "./editors";
export class MapStage {
export class MapEditor {
dom: HTMLDivElement;
private _map: AMap.Map | undefined;
private rectangleEditor: RectangleEditor | undefined;
constructor(dom: HTMLDivElement) {
this.dom = dom;
}
get map() {
return this._map;
return this._map!;
}
async init() {
@ -25,5 +28,17 @@ export class MapStage {
],
});
this._map = new AMap.Map(this.dom);
this.initEditors();
}
update(state: IMapState) {
if (state.status === "createOverlay") {
this.rectangleEditor?.create();
}
}
initEditors() {
const { map } = this;
this.rectangleEditor = new RectangleEditor(map);
}
}

18
src/store/actions.ts

@ -0,0 +1,18 @@
export enum ActionTypes {
AddRect = "addRect",
CreateOverlay = "createOverlay",
}
export class EditorAction {
addRect() {
return {
type: ActionTypes.AddRect,
};
}
createOverlay(type: string) {
return {
type: ActionTypes.CreateOverlay,
payload: type,
};
}
}

13
src/store/index.ts

@ -2,6 +2,9 @@ import { createStore, Store } from "redux";
import { createContext, Context, useContext } from "react";
import { reducer, Action } from "./reducers";
import { IEditorState } from "./type";
import { EditorAction } from "./actions";
export * from "./type";
type IStore = Store<IEditorState, Action>;
const store: IStore = createStore(reducer);
@ -24,11 +27,13 @@ export { store };
// }
// }
export const editorAction = new EditorAction();
export const StoreContext = createContext<IStore | null>(
null
) as Context<IStore>;
export const useStore = () => {
const store = useContext(StoreContext);
return store;
};
// export const useStore = () => {
// const store = useReduxContext(StoreContext);
// return store;
// };

2
src/store/initState.ts

@ -2,6 +2,8 @@ import { IEditorState } from "./type";
export const initState: IEditorState = {
map: {
status: "",
overlayType: "",
polygons: [],
},
};

24
src/store/reducers.ts

@ -1,11 +1,27 @@
import { createStore } from "redux";
import { initState } from "./initState";
import { ActionTypes } from "./actions";
import { IEditorState } from "./type";
export type Action = {
type: string;
payload: any;
type: ActionTypes;
payload?: any;
};
export function reducer(state = initState, action: Action) {
return state;
export function reducer(state = initState, action: Action): IEditorState {
const { type, payload } = action;
switch (type) {
case ActionTypes.CreateOverlay:
return {
...state,
map: {
...state.map,
status: "createOverlay",
overlayType: payload as string,
},
//
};
default:
return state;
}
}

2
src/store/type.ts

@ -4,6 +4,8 @@ export interface IPolygon {
}
export interface IMapState {
status: string;
overlayType: string;
polygons: IPolygon[];
}

6
src/types/index.d.ts vendored

@ -1,6 +0,0 @@
declare global {
namespace AMapLoader {
const load: (config: any) => Promise<AMap.Map>;
}
}
export {};

22
src/types/index.ts

@ -0,0 +1,22 @@
declare global {
namespace AMapLoader {
const load: (config: any) => Promise<AMap.Map>;
}
namespace AMap {
interface IBaseEditor {
// new (map: AMap.Map): any;
}
class BaseEditor implements IBaseEditor {
constructor(map: AMap.Map);
setTarget(target: any): void;
open(): void;
}
class PolygonEditor extends BaseEditor {
//
}
class RectangleEditor extends BaseEditor {
//
}
}
}
export {};

8
tsconfig.json

@ -14,7 +14,13 @@
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
"jsx": "react-jsx",
"paths": {
"@store": ["./src/store"],
"@editor": ["./src/editor"],
"@map": ["./src/map"],
"@types": ["./src/types"],
}
},
"include": ["./src"]
}

9
vite.config.js

@ -1,5 +1,5 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import path from "path";
// https://vitejs.dev/config/
@ -9,11 +9,12 @@ export default defineConfig({
alias: {
"@store": path.resolve(__dirname, "src/store"),
"@editor": path.resolve(__dirname, "src/editor"),
"@map": path.resolve(__dirname, "src/map"),
"@app": path.resolve(__dirname, "src/app"),
"@types": path.resolve(__dirname, "src/types"),
},
},
server: {
port: 8080
port: 8080,
},
})
});

9186
yarn.lock

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save