Browse Source

feat: 支持添加标记点

master
Cmen 3 years ago
parent
commit
b4d9ece671
  1. BIN
      public/images/marker.png
  2. 11
      src/editor/Catalog/index.tsx
  3. 1
      src/editor/Plot/Tools/index.tsx
  4. 2
      src/icon.less
  5. 5
      src/index.less
  6. 91
      src/map/MapEditor.ts
  7. 1
      src/map/type.ts
  8. 1
      src/store/actions/index.ts
  9. 1
      src/store/constants.ts
  10. 2
      src/store/reducers/map/index.ts
  11. 4
      src/types/amap.d.ts

BIN
public/images/marker.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

11
src/editor/Catalog/index.tsx

@ -40,7 +40,8 @@ const Catalog = () => {
const rectangles: IOverlay[] = [],
polygons: IOverlay[] = [],
polylines: IOverlay[] = [],
circles: IOverlay[] = [];
circles: IOverlay[] = [],
points: IOverlay[] = [];
overlays.forEach((overlay) => {
switch (overlay.type) {
@ -53,6 +54,9 @@ const Catalog = () => {
case OverlayTypes.Polyline:
polylines.push(overlay);
break;
case OverlayTypes.Point:
points.push(overlay);
break;
default:
circles.push(overlay);
}
@ -60,7 +64,7 @@ const Catalog = () => {
return (
<Collapse
defaultActiveKey={["1", "2", "3", "4"]}
defaultActiveKey={["1", "2", "3", "4", "5"]}
expandIconPosition="right"
>
<Panel header="矩形" key={1}>
@ -75,6 +79,9 @@ const Catalog = () => {
<Panel header="圆形" key={4}>
<OverlayList overlays={circles} />
</Panel>
<Panel header="标记点" key={5}>
<OverlayList overlays={points} />
</Panel>
</Collapse>
);
};

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

@ -67,6 +67,7 @@ const Tools = () => {
<OverlayTool type={OverlayTypes.Polygon} hotkey="Alt+2" />
<OverlayTool type={OverlayTypes.Polyline} hotkey="Alt+3" />
<OverlayTool type={OverlayTypes.Circle} hotkey="Alt+4" />
<OverlayTool type={OverlayTypes.Point} hotkey="Alt+5" />
</div>
<div className="common-tools">
<div className="tools-group">

2
src/icon.less

@ -63,7 +63,7 @@
.icon-setting:after {
content: "\e78e";
}
.icon-location:after {
.icon-point:after {
content: "\e793";
}
.icon-rectangle:after {

5
src/index.less

@ -9,3 +9,8 @@ body {
#app {
height: 100%;
}
.amap-icon img,
.amap-marker-content img{
width: 25px;
height: 34px;
}

91
src/map/MapEditor.ts

@ -157,23 +157,21 @@ export class MapEditor extends Emitter implements IMapEditor {
createOverlay(type: OverlayTypes) {
this.finishEditOverlay();
if (type === OverlayTypes.Point) {
this._createMarker();
} else {
this.currentOverlayEditor = this.getEditorByType(type!);
this.currentOverlayEditor?.create();
this.editorStatus = "creating";
}
}
selectOverlays(ids?: string[]) {
this.finishEditOverlay();
this.selectedIds?.forEach((id) => {
const { target, type } = this.overlayMap[id];
target.setOptions(getOverlayOptions(type));
});
this.selectedIds?.forEach((id) => this._updateOverlayProps(id));
if (ids == null) return;
this.selectedIds = ids;
ids.forEach((id) => {
const { target } = this.overlayMap[id];
target.setOptions(SelectedOptions);
});
ids.forEach((id) => this._updateOverlayProps(id, true));
}
deleteOverlays() {
@ -199,9 +197,7 @@ export class MapEditor extends Emitter implements IMapEditor {
let id = getUID();
if (isCreatingOverlay) {
this._addOverlay(id, { type, target });
target.setOptions(
type === OverlayTypes.Polyline ? PolylineOptions : PolygonOptions
);
this._updateOverlayProps(id);
} else {
id = this.selectedIds[0];
}
@ -237,17 +233,61 @@ export class MapEditor extends Emitter implements IMapEditor {
this.placeSearch?.search(item.name);
}
editSelectedOverlay() {
if (this.selectedIds.length !== 1) return;
const [id] = this.selectedIds;
const { target, type } = this.overlayMap[id];
this.currentOverlayEditor = this.getEditorByType(type);
this.currentOverlayEditor?.edit(target);
this.editorStatus = "editing";
}
getOverlay(id: string) {
return this.overlayMap[id];
}
_createMarker() {
const id = getUID();
const marker = this._buildMarker(this.getCenter());
this._addOverlay(id, { type: OverlayTypes.Point, target: marker });
this._updateOverlay(id);
}
_buildMarker(position: number[]) {
const marker = new AMap.Marker({
icon: "/images/marker.png",
position: position as [number, number],
anchor: "bottom-center",
offset: new AMap.Pixel(-13, -30),
});
marker.setMap(this.map);
this.map.add(marker);
return marker;
}
_updateOverlayProps(id: string, selected = false) {
const { type, target } = this.getOverlay(id);
if (type === OverlayTypes.Point) {
target.setOptions({ draggable: selected });
} else {
target.setOptions(selected ? SelectedOptions : getOverlayOptions(type));
}
}
_buildFromOverlay(overlay: IOverlay) {
const { type, id } = overlay;
let target: AMap.MapOverlay;
if (type === OverlayTypes.Point) {
target = this._buildMarker(overlay.lngLat!);
} else {
const editor = this.overlayEditors.find(
(editor) => editor.getType() === type
)!;
const target = editor.build(overlay);
this._addOverlay(id, { type, target });
target.setOptions(
type === OverlayTypes.Polyline ? PolylineOptions : PolygonOptions
);
target = editor.build(overlay);
this.map.add(target);
}
this._addOverlay(id, { type, target });
this._updateOverlayProps(id);
if (overlay.backgroundImage) {
this.updateOverlayBackground(id, overlay.backgroundImage);
}
@ -257,7 +297,11 @@ export class MapEditor extends Emitter implements IMapEditor {
if (this.overlayMap[id] == null) return;
const { type, target } = this.overlayMap[id];
const evt: any = { id, type };
if (type === OverlayTypes.Circle) {
if (type === OverlayTypes.Point) {
const marker = target as AMap.Marker;
const { lng, lat } = marker.getPosition()!;
evt.lngLat = [lng, lat];
} else if (type === OverlayTypes.Circle) {
const circle = target as AMap.Circle;
const { lng, lat } = circle.getCenter();
evt.lngLat = [lng, lat];
@ -269,21 +313,12 @@ export class MapEditor extends Emitter implements IMapEditor {
this.updateOverlayBackground(id);
}
editSelectedOverlay() {
if (this.selectedIds.length !== 1) return;
const [id] = this.selectedIds;
const { target, type } = this.overlayMap[id];
this.currentOverlayEditor = this.getEditorByType(type);
this.currentOverlayEditor?.edit(target);
this.editorStatus = "editing";
}
onOverlayDragEnd(id: string) {
_onOverlayDragEnd(id: string) {
this._updateOverlay(id);
}
_addOverlay(id: string, overlay: OverlayTemp) {
this.overlayMap[id] = overlay;
overlay.target.on("dragend", () => this.onOverlayDragEnd(id));
overlay.target.on("dragend", () => this._onOverlayDragEnd(id));
}
}

1
src/map/type.ts

@ -46,4 +46,5 @@ export enum OverlayTypes {
Polygon = "polygon",
Polyline = "polyline",
Circle = "circle",
Point = "point",
}

1
src/store/actions/index.ts

@ -52,6 +52,7 @@ export class EditorAction {
// 创建覆盖物结束
this.mapEditor.on(EventTypes.FinishEditOverlay, (overlay: IOverlay) => {
this.dispatch(StoreAction.finishEditOverlay(overlay));
this.selectOverlay(overlay.id);
});
}

1
src/store/constants.ts

@ -5,4 +5,5 @@ export const OverlayNamePrefixs: Record<OverlayTypes, string> = {
[OverlayTypes.Polygon]: "多边形",
[OverlayTypes.Polyline]: "多段线",
[OverlayTypes.Circle]: "圆形",
[OverlayTypes.Point]: "标记点",
};

2
src/store/reducers/map/index.ts

@ -31,7 +31,6 @@ export function finishEditOverlay(state = initState, payload: any) {
const overlay = payload as IOverlay;
const { type, id } = overlay;
// todo: uniqueName.
overlay.name = OverlayNamePrefixs[type] + overlay.id;
const { overlays } = draft.map;
const existed = overlays.find((overlay) => overlay.id === id);
if (existed) {
@ -40,6 +39,7 @@ export function finishEditOverlay(state = initState, payload: any) {
...overlay,
};
} else {
overlay.name = OverlayNamePrefixs[type] + overlay.id;
const isRoad = type === OverlayTypes.Polyline;
if (isRoad) {
overlay.category = OverlayCategory.Road;

4
src/types/amap.d.ts vendored

@ -7,10 +7,14 @@ declare global {
interface IBaseEditor {
// new (map: AMap.Map): any;
}
interface Marker {
setOptions(options: { [name: string]: any }): void;
}
type MapOverlay =
| AMap.Rectangle
| AMap.Polygon
| AMap.Polyline
| AMap.Marker
| AMap.Circle;
class BaseEditor implements IBaseEditor {
constructor(map: AMap.Map);

Loading…
Cancel
Save