我想让用户能够在NextJs中的LeafletMap上使用Geoman进行CRUD操作。我的代码可以很好地创建和删除层,但是当我试图编辑我的层时(无论是移动它们,向它们添加额外的点,还是在它们中切割洞),尽管我试图为此添加合适的事件,但什么也没有发生。
下面是我的Map.tsx,我在这里生成我的Map:
import "leaflet/dist/leaflet.css";
import { LayersControl, MapContainer, TileLayer } from "react-leaflet";
import "leaflet/dist/leaflet.css";
import "leaflet";
import "@geoman-io/leaflet-geoman-free";
import "@geoman-io/leaflet-geoman-free/dist/leaflet-geoman.css";
import { v4 as uuidv4 } from "uuid";
import React, { useState } from "react";
import type { FC } from "react";
import * as L from "leaflet";
import { GeomanControl } from "./GeomanControl";
import { DoneControl } from "./DoneButton";
import { CancelControl } from "./CancelButton";
interface IMapProps {
isDone: boolean;
setIsDone: (isDone: boolean) => void;
}
interface MyLayer extends L.Layer {
_leaflet_id?: string;
coords:
| L.LatLngExpression[]
| L.LatLngExpression[][]
| L.LatLngExpression[][][];
}
const Map: FC<IMapProps> = ({ isDone, setIsDone }) => {
const washingtonDC = L.latLng(38.9072, -77.0369);
const mapStyle = { height: "100vh", width: "100%", padding: 0 };
const [polygons, setPolygons] = useState<
{
id: string;
coords:
| L.LatLngExpression[]
| L.LatLngExpression[][]
| L.LatLngExpression[][][];
}[]
>([]);
console.log(isDone);
return (
<React.Fragment>
<MapContainer
center={washingtonDC}
zoom={8}
zoomControl={false}
style={mapStyle}
//whenReady={() => {}}
>
<TileLayer
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<GeomanControl
position="bottomleft"
oneBlock
onCreate={(layer) => {
// Get the layer's coordinates and update the state variable
const latlngs = (layer as L.Polygon).getLatLngs();
// Generate a unique ID for the polygon
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const id = uuidv4() as string;
// Add the polygon to the state
setPolygons((prevPolygons) => [
...prevPolygons,
{ id, coords: latlngs },
]);
// Assign the ID to the layer
(layer as MyLayer)._leaflet_id = id;
}}
onUpdate={(layer) => {
const latlngs = (layer as L.Polygon).getLatLngs();
const id = (layer as MyLayer)._leaflet_id;
console.log("Updated coordinates:", latlngs);
setPolygons((prevPolygons) =>
prevPolygons.map((polygon) =>
polygon.id === id ? { id, coords: latlngs } : polygon
)
);
}}
onRemove={(layer) => {
const id = (layer as MyLayer)._leaflet_id;
setPolygons((prevPolygons) =>
prevPolygons.filter((polygon) => polygon.id !== id)
);
}}
/>
<DoneControl
position="topright"
clickHandler={() => {
console.log("Done button clicked!");
setIsDone(true);
console.log("isDone: ", isDone);
}}
/>
<CancelControl />
{/* Display different map layers */}
<LayersControl position="topright">
<LayersControl.BaseLayer checked name="OpenStreetMap.Mapnik">
<TileLayer
zIndex={1}
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
maxNativeZoom={19}
maxZoom={25}
/>
</LayersControl.BaseLayer>
<LayersControl.BaseLayer name="MapBox.Satellite">
<TileLayer
zIndex={1}
attribution='Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>'
url={`https://api.mapbox.com/styles/v1/${"mapbox/satellite-streets-v11"}/tiles/{z}/{x}/{y}?access_token=${
process.env.NEXT_PUBLIC_MAPBOX_TOKEN || ""
}`}
maxNativeZoom={21}
maxZoom={25}
/>
</LayersControl.BaseLayer>
<LayersControl.BaseLayer name="MapBox.Outdoors">
<TileLayer
zIndex={1}
attribution='Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>'
url={`https://api.mapbox.com/styles/v1/${"mapbox/outdoors-v11"}/tiles/{z}/{x}/{y}?access_token=${
process.env.NEXT_PUBLIC_MAPBOX_TOKEN || ""
}`}
maxNativeZoom={21}
maxZoom={25}
/>
</LayersControl.BaseLayer>
</LayersControl>
</MapContainer>
</React.Fragment>
);
};
export default Map;
下面是我的GeomanControl.tsx:
import { createControlComponent } from "@react-leaflet/core";
import * as L from "leaflet";
import "leaflet/dist/leaflet.css";
import "@geoman-io/leaflet-geoman-free";
import "@geoman-io/leaflet-geoman-free/dist/leaflet-geoman.css";
interface Props extends L.ControlOptions {
position: L.ControlPosition;
drawCircle?: boolean;
oneBlock?: boolean;
onCreate: (layer: MyLayer) => void;
onRemove: (layer: MyLayer) => void;
onUpdate: (layer: MyLayer) => void;
}
interface MyLayer extends L.Layer {
_leaflet_id?: string;
}
class Geoman extends L.Control {
options: Props;
constructor(options: Props) {
super(options);
this.options = options;
}
onAdd(map: L.Map): HTMLElement {
if (map.pm) {
map.pm.addControls({
position: this.options.position,
oneBlock: this.options.oneBlock,
drawCircleMarker: false,
drawMarker: false,
drawPolyline: false,
drawText: false,
drawCircle: false,
});
// When a layer is created by drawing or importing data
map.on("pm:create", (e: { layer: MyLayer }) => {
if (this.options.onCreate) {
this.options.onCreate(e.layer);
}
});
// When a layer is updated
map.on("pm:update", (e: { layer: MyLayer }) => {
if (this.options.onUpdate) {
this.options.onUpdate(e.layer);
}
});
// When a layer is updated
map.on("pm:change", (e: { layer: MyLayer }) => {
if (this.options.onUpdate) {
this.options.onUpdate(e.layer);
}
});
// When a layer is dragged
map.on("pm:dragend", (e: { layer: MyLayer }) => {
if (this.options.onUpdate) {
this.options.onUpdate(e.layer);
}
});
// When a layer's vertices are edited
map.on("pm:edit", (e: { layer: MyLayer }) => {
if (this.options.onUpdate) {
this.options.onUpdate(e.layer);
}
});
// When a layer is cut, edited, or dragged
map.on("pm:cut", (e: { layer: L.Layer }) => {
if (this.options.onUpdate) {
this.options.onUpdate(e.layer);
}
});
}
return L.DomUtil.create("div");
}
onRemove(map: L.Map): void {
if (map.pm) {
map.pm.removeControls();
}
map.off("pm:create");
map.off("pm:update");
map.off("pm:update");
map.off("pm:dragend");
map.off("pm:edit");
map.off("pm:cut");
map.on("pm:remove", (e: { layer: MyLayer }) => {
if (this.options.onRemove) {
this.options.onRemove(e.layer);
}
});
}
}
const createGeomanInstance = (props: Props) => new Geoman(props);
export const GeomanControl = createControlComponent(createGeomanInstance);
1条答案
按热度按时间oymdgrw71#
我有这样的问题,兄弟!如果你找到任何解决方案,请让我知道他们!我也在找呢!