I have a Leaflet responsive map, which I am using in react. My map is a custom floor plan and it is in svg. I have setup the map with "ImageOverlay" and everything is working fine. Now my problem is happening only when I am using point (x, y) coordinates and converting it to lat, lng. The lat, lng is changing based on screen size. I need a fixed lat, lng respective of the screen size so that I can show a marker. Currently if I show a marker based on the screen size the marker position is showing at different places. So my question is how to get lat, lng irrespective of the screen size? Here is my code:
L.CRS.Simple = L.extend({}, L.CRS, {
projection: L.Projection.LonLat,
transformation: new L.Transformation(1, 0, 1, 0)
});
const mapHeight = 400;
const mapWidth = 100;
const svgImageWidth = 2245;
const svgImageHeight = 1587;
const initState = {
mapBounds: [[0, 0], [1000, 1000]],
mapMarkerPosition: [40.751, -74.17],
mapZoom: 4,
mapCenter: [40.74400563300867, -74.1680145263672],
xCoordinate: "",
yCoordinate: "",
coordinates: { x: 292, y: 89 }
};
export default function App() {
const mapRef = useRef(null);
const [state, setState] = useState(initState);
function getBoundsUnproject(map) {
const southWest = map.unproject([0, svgImageHeight], 6);
const northEast = map.unproject([svgImageWidth, 0], 6);
const bounds = new L.LatLngBounds(southWest, northEast);
map.setMaxBounds(bounds);
return { bounds };
}
React.useEffect(() => {
const map = mapRef.current.leafletElement;
if (map) {
const { bounds } = getBoundsUnproject(map);
console.log("bounds", bounds);
map.fitBounds(bounds);
const centerLatLng = map.getCenter();
console.log("center", centerLatLng);
const customCoordinates = state.coordinates;
// console.log("customCoordinates", customCoordinates);
const point = L.point(customCoordinates.x, customCoordinates.y);
const customCoordinatesLatLng = map.containerPointToLatLng(point);
console.log("customCoordinatesLatLng", customCoordinatesLatLng);
setState(prevState => ({
...prevState,
mapBounds: [
[bounds._northEast.lat, bounds._northEast.lng],
[bounds._southWest.lat, bounds._southWest.lng]
],
mapMarkerPosition: [
customCoordinatesLatLng.lat,
customCoordinatesLatLng.lng
]
}));
}
}, [state.coordinates]);
function handleChange(event) {
const name = event.target.name;
const value = event.target.value;
if (isNaN(value)) {
return;
}
setState(prevState => ({
...prevState,
[name]: value
}));
}
function handleClick() {
setState(prevState => ({
...prevState,
coordinates: { x: state.xCoordinate, y: state.yCoordinate }
}));
}
return (
<div className="container-fluid">
<div className="row justify-content-center mt-5">
<div className="col-md-6">
<div className="row justify-content-center">
<div className="col-md-4">
<input
style={{ width: "100%" }}
type="text"
value={state.xCoordinate}
onChange={handleChange}
name="xCoordinate"
placeholder="x coordinate (default: 292)"
/>
</div>
<div className="col-md-4">
<input
style={{ width: "100%" }}
type="text"
value={state.yCoordinate}
onChange={handleChange}
name="yCoordinate"
placeholder="y coordinate (default: 89)"
/>
</div>
<div className="col-md-2">
<button onClick={handleClick}>Submit</button>
</div>
</div>
</div>
</div>
<div className="row justify-content-center mt-5 mb-5">
<div className="col-6">
<LeafletMap
ref={mapRef}
crs={L.CRS.Simple}
center={state.mapCenter}
zoom={state.mapZoom}
minZoom={state.mapZoom}
style={{ height: `${mapHeight}px`, width: `${mapWidth}%` }}
>
<ImageOverlay
bounds={state.mapBounds}
url={"image-url"}
>
<Marker
position={state.mapMarkerPosition}
icon={customMarkerIcon}
/>
</ImageOverlay>
</LeafletMap>
</div>
</div>
</div>
);
}
It would be helpful if someone points out what am I doing wrong.
Thanks.