Browse Source

全局快捷键实现

master
Cmen 3 years ago
parent
commit
ec77899def
  1. 1
      package.json
  2. 110
      src/store/GlobalController.ts
  3. 30
      src/store/index.ts
  4. 7
      src/store/type.ts
  5. 25
      src/store/utils/getGeoJSON.ts
  6. 36
      src/types/amap.d.ts
  7. 35
      src/types/index.ts
  8. 5
      yarn.lock

1
package.json

@ -21,6 +21,7 @@
}, },
"devDependencies": { "devDependencies": {
"@amap/amap-jsapi-types": "^0.0.8", "@amap/amap-jsapi-types": "^0.0.8",
"@types/geojson": "^7946.0.8",
"@types/react": "^17.0.33", "@types/react": "^17.0.33",
"@types/react-dom": "^17.0.10", "@types/react-dom": "^17.0.10",
"@vitejs/plugin-react": "^1.0.7", "@vitejs/plugin-react": "^1.0.7",

110
src/store/GlobalController.ts

@ -0,0 +1,110 @@
import { IStore } from "./type";
import { registerHotkey } from "@utils";
import { getGeoJSON } from "./utils/getGeoJSON";
import { OverlayTypes } from "../types/enum";
import { EditorAction } from "./actions";
interface IGlobalController {
saveGeoJSON: () => void;
saveProject: () => void;
saveTemp: () => void;
clearEditor: () => void;
openGeoJSON: () => void;
openProject: () => void;
showCommand: () => void;
createRectangle: () => void;
createPolygon: () => void;
createPolyline: () => void;
createCircle: () => void;
}
// 全局控制器, 用以复用一些快捷方法.
export class GlobelController implements IGlobalController {
_store: IStore;
constructor(store: IStore) {
this._store = store;
this._bindOperations();
this._registerHotkeys();
}
get mapState() {
return this._store.getState().map;
}
saveGeoJSON() {
const geojson = getGeoJSON(this.mapState);
console.log(geojson);
}
saveProject() {
//
}
saveTemp() {
//
}
clearEditor() {
//
}
openGeoJSON() {
//
}
openProject() {
//
}
showCommand() {
//
}
createRectangle() {
this._createOverlay(OverlayTypes.Rectangle);
}
createPolygon() {
this._createOverlay(OverlayTypes.Polygon);
}
createPolyline() {
this._createOverlay(OverlayTypes.Polyline);
}
createCircle() {
this._createOverlay(OverlayTypes.Circle);
}
private _createOverlay(type: OverlayTypes) {
this._store.dispatch(EditorAction.createOverlay(type));
}
private _bindOperations() {
this.saveGeoJSON = this.saveGeoJSON.bind(this);
this.createRectangle = this.createRectangle.bind(this);
this.createPolygon = this.createPolygon.bind(this);
this.createPolyline = this.createPolyline.bind(this);
this.createCircle = this.createCircle.bind(this);
}
private _registerHotkeys() {
registerHotkey("s", { callback: this.saveGeoJSON, ctrl: true });
registerHotkey("s", {
callback: this.saveProject,
ctrl: true,
alt: true,
});
registerHotkey("s", { callback: this.saveTemp, alt: true });
registerHotkey("c", { callback: this.clearEditor, alt: true });
registerHotkey("o", { callback: this.openGeoJSON, alt: true });
registerHotkey("o", {
callback: this.openProject,
alt: true,
ctrl: true,
});
registerHotkey("p", { callback: this.showCommand, alt: true });
registerHotkey("1", {
callback: this.createRectangle,
alt: true,
});
registerHotkey("2", { callback: this.createPolygon, alt: true });
registerHotkey("3", {
callback: this.createPolyline,
alt: true,
});
registerHotkey("4", { callback: this.createCircle, alt: true });
// registerHotkey("5", { callback: () => {}, alt: true });
}
}

30
src/store/index.ts

@ -1,22 +1,28 @@
import { createStore, Store } from "redux"; import { createStore } from "redux";
import { createContext, Context } from "react"; // import { createContext, Context } from "react";
import { reducer, Action } from "./reducers"; import { reducer } from "./reducers";
import { IEditorState } from "./type"; import { IStore } from "./type";
import { EditorAction } from "./actions"; import { EditorAction } from "./actions";
import { GlobelController } from "./GlobalController";
export * from "./type"; export * from "./type";
export * from "./selectors"; export * from "./selectors";
export * from "./constants"; export * from "./constants";
type IStore = Store<IEditorState, Action>; export { EditorAction };
const store: IStore = createStore(reducer);
(window as any).store = store; declare global {
interface Window {
store: IStore;
}
}
export { store }; export const store: IStore = createStore(reducer);
export { EditorAction }; export const globalController = new GlobelController(store);
window.store = store;
export const StoreContext = createContext<IStore | null>( // export const StoreContext = createContext<IStore | null>(
null // null
) as Context<IStore>; // ) as Context<IStore>;

7
src/store/type.ts

@ -1,11 +1,14 @@
import { Store } from "redux";
import { Action } from "./reducers";
import { OverlayTypes, Status, Command } from "@types"; import { OverlayTypes, Status, Command } from "@types";
export type IStore = Store<IEditorState, Action>;
export interface IOverlay { export interface IOverlay {
id: string; id: string;
name: string; name: string;
type: OverlayTypes; type: OverlayTypes;
lngLat?: number[]; lngLat?: GeoJSON.Position;
paths?: number[][]; path?: GeoJSON.Position[];
radius?: number; radius?: number;
} }
export interface IMapState { export interface IMapState {

25
src/store/utils/getGeoJSON.ts

@ -0,0 +1,25 @@
import { IMapState } from "../type";
export function getGeoJSON(state: IMapState): GeoJSON.FeatureCollection {
//
const features: GeoJSON.Feature[] = [];
const { rectangles, polygons, polylines, circles } = state;
rectangles.forEach((rect) => {
const path = rect.path!;
features.push({
type: "Feature",
geometry: {
type: "MultiPolygon",
coordinates: [[path]],
},
properties: {},
});
});
return {
type: "FeatureCollection",
features,
};
}

36
src/types/amap.d.ts vendored

@ -0,0 +1,36 @@
import "@amap/amap-jsapi-types";
declare global {
namespace AMapLoader {
const load: (config: any) => Promise<AMap.Map>;
}
namespace AMap {
interface IBaseEditor {
// new (map: AMap.Map): any;
}
type MapOverlay =
| AMap.Rectangle
| AMap.Polygon
| AMap.Polyline
| AMap.Circle;
class BaseEditor implements IBaseEditor {
constructor(map: AMap.Map);
setTarget(target: any): void;
getTarget(): MapOverlay;
open(): void;
close(): void;
destroy(): void;
}
class PolygonEditor extends BaseEditor {
//
}
class RectangleEditor extends BaseEditor {
//
}
class PolylineEditor extends BaseEditor {
//
}
class CircleEditor extends BaseEditor {
//
}
}
}

35
src/types/index.ts

@ -1,36 +1 @@
declare global {
namespace AMapLoader {
const load: (config: any) => Promise<AMap.Map>;
}
namespace AMap {
interface IBaseEditor {
// new (map: AMap.Map): any;
}
type MapOverlay =
| AMap.Rectangle
| AMap.Polygon
| AMap.Polyline
| AMap.Circle;
class BaseEditor implements IBaseEditor {
constructor(map: AMap.Map);
setTarget(target: any): void;
getTarget(): MapOverlay;
open(): void;
close(): void;
destroy(): void;
}
class PolygonEditor extends BaseEditor {
//
}
class RectangleEditor extends BaseEditor {
//
}
class PolylineEditor extends BaseEditor {
//
}
class CircleEditor extends BaseEditor {
//
}
}
}
export * from "./enum"; export * from "./enum";

5
yarn.lock

@ -1361,6 +1361,11 @@
resolved "https://registry.npmmirror.com/@rushstack/eslint-patch/download/@rushstack/eslint-patch-1.1.0.tgz#7f698254aadf921e48dda8c0a6b304026b8a9323" resolved "https://registry.npmmirror.com/@rushstack/eslint-patch/download/@rushstack/eslint-patch-1.1.0.tgz#7f698254aadf921e48dda8c0a6b304026b8a9323"
integrity sha1-f2mCVKrfkh5I3ajAprMEAmuKkyM= integrity sha1-f2mCVKrfkh5I3ajAprMEAmuKkyM=
"@types/geojson@^7946.0.8":
version "7946.0.8"
resolved "https://registry.npmmirror.com/@types/geojson/-/geojson-7946.0.8.tgz#30744afdb385e2945e22f3b033f897f76b1f12ca"
integrity sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==
"@types/hoist-non-react-statics@^3.3.0": "@types/hoist-non-react-statics@^3.3.0":
version "3.3.1" version "3.3.1"
resolved "https://registry.npmmirror.com/@types/hoist-non-react-statics/download/@types/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" resolved "https://registry.npmmirror.com/@types/hoist-non-react-statics/download/@types/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"

Loading…
Cancel
Save