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

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

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

2
src/icon.less

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

5
src/index.less

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

103
src/map/MapEditor.ts

@ -157,23 +157,21 @@ export class MapEditor extends Emitter implements IMapEditor {
createOverlay(type: OverlayTypes) { createOverlay(type: OverlayTypes) {
this.finishEditOverlay(); this.finishEditOverlay();
this.currentOverlayEditor = this.getEditorByType(type!); if (type === OverlayTypes.Point) {
this.currentOverlayEditor?.create(); this._createMarker();
this.editorStatus = "creating"; } else {
this.currentOverlayEditor = this.getEditorByType(type!);
this.currentOverlayEditor?.create();
this.editorStatus = "creating";
}
} }
selectOverlays(ids?: string[]) { selectOverlays(ids?: string[]) {
this.finishEditOverlay(); this.finishEditOverlay();
this.selectedIds?.forEach((id) => { this.selectedIds?.forEach((id) => this._updateOverlayProps(id));
const { target, type } = this.overlayMap[id];
target.setOptions(getOverlayOptions(type));
});
if (ids == null) return; if (ids == null) return;
this.selectedIds = ids; this.selectedIds = ids;
ids.forEach((id) => { ids.forEach((id) => this._updateOverlayProps(id, true));
const { target } = this.overlayMap[id];
target.setOptions(SelectedOptions);
});
} }
deleteOverlays() { deleteOverlays() {
@ -199,9 +197,7 @@ export class MapEditor extends Emitter implements IMapEditor {
let id = getUID(); let id = getUID();
if (isCreatingOverlay) { if (isCreatingOverlay) {
this._addOverlay(id, { type, target }); this._addOverlay(id, { type, target });
target.setOptions( this._updateOverlayProps(id);
type === OverlayTypes.Polyline ? PolylineOptions : PolygonOptions
);
} else { } else {
id = this.selectedIds[0]; id = this.selectedIds[0];
} }
@ -237,17 +233,61 @@ export class MapEditor extends Emitter implements IMapEditor {
this.placeSearch?.search(item.name); 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) { _buildFromOverlay(overlay: IOverlay) {
const { type, id } = overlay; const { type, id } = overlay;
const editor = this.overlayEditors.find( let target: AMap.MapOverlay;
(editor) => editor.getType() === type if (type === OverlayTypes.Point) {
)!; target = this._buildMarker(overlay.lngLat!);
const target = editor.build(overlay); } else {
const editor = this.overlayEditors.find(
(editor) => editor.getType() === type
)!;
target = editor.build(overlay);
this.map.add(target);
}
this._addOverlay(id, { type, target }); this._addOverlay(id, { type, target });
target.setOptions( this._updateOverlayProps(id);
type === OverlayTypes.Polyline ? PolylineOptions : PolygonOptions
);
this.map.add(target);
if (overlay.backgroundImage) { if (overlay.backgroundImage) {
this.updateOverlayBackground(id, overlay.backgroundImage); this.updateOverlayBackground(id, overlay.backgroundImage);
} }
@ -257,7 +297,11 @@ export class MapEditor extends Emitter implements IMapEditor {
if (this.overlayMap[id] == null) return; if (this.overlayMap[id] == null) return;
const { type, target } = this.overlayMap[id]; const { type, target } = this.overlayMap[id];
const evt: any = { id, type }; 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 circle = target as AMap.Circle;
const { lng, lat } = circle.getCenter(); const { lng, lat } = circle.getCenter();
evt.lngLat = [lng, lat]; evt.lngLat = [lng, lat];
@ -269,21 +313,12 @@ export class MapEditor extends Emitter implements IMapEditor {
this.updateOverlayBackground(id); this.updateOverlayBackground(id);
} }
editSelectedOverlay() { _onOverlayDragEnd(id: string) {
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) {
this._updateOverlay(id); this._updateOverlay(id);
} }
_addOverlay(id: string, overlay: OverlayTemp) { _addOverlay(id: string, overlay: OverlayTemp) {
this.overlayMap[id] = overlay; 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", Polygon = "polygon",
Polyline = "polyline", Polyline = "polyline",
Circle = "circle", 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.mapEditor.on(EventTypes.FinishEditOverlay, (overlay: IOverlay) => {
this.dispatch(StoreAction.finishEditOverlay(overlay)); 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.Polygon]: "多边形",
[OverlayTypes.Polyline]: "多段线", [OverlayTypes.Polyline]: "多段线",
[OverlayTypes.Circle]: "圆形", [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 overlay = payload as IOverlay;
const { type, id } = overlay; const { type, id } = overlay;
// todo: uniqueName. // todo: uniqueName.
overlay.name = OverlayNamePrefixs[type] + overlay.id;
const { overlays } = draft.map; const { overlays } = draft.map;
const existed = overlays.find((overlay) => overlay.id === id); const existed = overlays.find((overlay) => overlay.id === id);
if (existed) { if (existed) {
@ -40,6 +39,7 @@ export function finishEditOverlay(state = initState, payload: any) {
...overlay, ...overlay,
}; };
} else { } else {
overlay.name = OverlayNamePrefixs[type] + overlay.id;
const isRoad = type === OverlayTypes.Polyline; const isRoad = type === OverlayTypes.Polyline;
if (isRoad) { if (isRoad) {
overlay.category = OverlayCategory.Road; overlay.category = OverlayCategory.Road;

4
src/types/amap.d.ts vendored

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

Loading…
Cancel
Save