I’m working with react-leaflet and react-leaflet-draw to create and edit shapes on a map. I can draw circles and rectangles, but I’m experiencing two specific issues:
1. I can’t resize the circle after it’s drawn: Although the move handler works, the resize handles for the circle don’t seem to function properly.
2. I can’t stretch the rectangle while drawing it: However, after the rectangle is drawn, I can resize and move it as expected.
import {
MapContainer,
TileLayer,
Marker,
Popup,
useMap,
FeatureGroup,
} from "react-leaflet";
import "leaflet/dist/leaflet.css";
import "leaflet-draw/dist/leaflet.draw.css";
import L from "leaflet";
import { FullscreenControl } from "react-leaflet-fullscreen";
import "react-leaflet-fullscreen/styles.css";
const EditControl = React.lazy(async () => {
const module = await import("react-leaflet-draw");
return { default: module.EditControl };
});
// @ts-ignore
import icon from "leaflet/dist/images/marker-icon.png";
// @ts-ignore
import iconShadow from "leaflet/dist/images/marker-shadow.png";
let DefaultIcon = L.icon({
iconUrl: icon,
shadowUrl: iconShadow,
iconAnchor: [12, 41],
});
L.Marker.prototype.options.icon = DefaultIcon;
const ChangeMapView = ({ center }) => {
const map = useMap();
useEffect(() => {
map.setView(center);
}, [center, map]);
return null;
};
const Map = () => {
const [sensors, setSensors] = useState([]);
const [mapCenter, setMapCenter] = useState([0, 0]);
const [sensorsInCircle, setSensorsInCircle] = useState([]);
useEffect(() => {
fetch("/sensors")
.then((res) => res.json())
.then((data) => {
setSensors(data);
if (data.length > 0) {
const { latitude, longitude } = data[0];
setMapCenter([latitude, longitude]);
}
})
.catch((err) => console.error("Error fetching data:", err));
}, []);
const onShapeCreated = (e) => {
const { layer, layerType } = e;
if (layerType === "circle") {
const radius = layer.getRadius();
const center = layer.getLatLng();
const sensorsInRange = sensors.filter((sensor) => {
const sensorLatLng = L.latLng(sensor.latitude, sensor.longitude);
return sensorLatLng.distanceTo(center) <= radius;
});
setSensorsInCircle(sensorsInRange);
alert(`Sensors in circle: ${sensorsInRange.length}`);
}
if (layerType === "rectangle") {
const bounds = layer.getBounds();
const sensorsInRectangle = sensors.filter((sensor) => {
const sensorLatLng = L.latLng(sensor.latitude, sensor.longitude);
return bounds.contains(sensorLatLng);
});
setSensorsInCircle(sensorsInRectangle);
alert(`Sensors in rectangle: ${sensorsInRectangle.length}`);
}
};
return (
// @ts-ignore
<MapContainer center={mapCenter} zoom={10} scrollWheelZoom={true} style={{ height: "500px", width: "100%" }}
>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
// @ts-ignore
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
/>
<FullscreenControl position="topleft" />
<ChangeMapView center={mapCenter} /> {/* Component to change map view */}
<FeatureGroup>
<React.Suspense fallback={<div>Loading...</div>}>
<EditControl
position="topright"
draw={{
polyline: false,
circlemarker: false,
marker: {
icon: DefaultIcon
},
rectangle: {
shapeOptions: {
color: '#ff7800',
weight: 1,
},
},
}}
onCreated={onShapeCreated}
/>
</React.Suspense>
</FeatureGroup>
{sensors.map((sensor) => (
<Marker
key={sensor.deviceId}
position={[sensor.latitude, sensor.longitude]}
>
<Popup>
<b>Device ID:</b> {sensor.deviceId} <br />
<b>Description:</b> {sensor.description} <br />
<b>Dimming Level:</b> {sensor.dimmingLevel}
</Popup>
</Marker>
))}
</MapContainer>
);
};
export default Map;