MouseCoordinates component for React Leaflet
React Leaflet is a React library that exposes Leaflet classes as React components, making it very easy to add interactive maps to React web apps.
This is the third in a series of posts on how I use the library. My intention is to share back some of the things I’ve learned and implemented in the hope of them being useful to others.
In this post, I present the MouseCoordinates
component which renders the
latitude and longitude that the mouse pointer hovers on and allows the user to
copy them by pressing Ctrl-C. You can see it in action on vouna.gr.
First, the component:
import React from 'react';
import { useMapEvents } from 'react-leaflet';
function round(number, precision = 0) {
return (
Math.round(number * Math.pow(10, precision) + Number.EPSILON) /
Math.pow(10, precision)
);
}
function formatLatitude(latitude) {
const direction = latitude > 0 ? 'N' : 'S';
return `${round(Math.abs(latitude), 6)}° ${direction}`;
}
function formatLongitude(longitude) {
const direction = longitude > 0 ? 'E' : 'W';
return `${round(Math.abs(longitude), 6)}° ${direction}`;
}
function MouseCoordinates() {
const [mousePoint, setMousePoint] = React.useState(null);
const formattedCoordinates =
mousePoint === null
? ''
: `${formatLatitude(mousePoint.lat)}, ${formatLongitude(mousePoint.lng)}`;
React.useEffect(
function copyToClipboard() {
function handleCtrlCKeydown(event) {
if (
event.key === 'c' && event.ctrlKey && formattedCoordinates.length > 0 &&
navigator.clipboard
) {
navigator.clipboard.writeText(formattedCoordinates);
}
}
document.addEventListener('keydown', handleCtrlCKeydown);
return function cleanup() {
document.removeEventListener('keydown', handleCtrlCKeydown);
};
},
[formattedCoordinates]
);
useMapEvents({
mousemove(event) {
setMousePoint(event.latlng);
},
mouseout() { setMousePoint(null); }, });
if (formattedCoordinates.length === 0) return null;
return (
<div className="leaflet-control-attribution leaflet-control"> {formattedCoordinates}
</div>
);
}
export default MouseCoordinates;
Things to note:
- Line 27:
formatLatitude
andformatLongitude
are used to format the coordinates - Lines 33-34: It is possible to copy the coordinates by pressing Ctrl-C
- Lines 55-57, 60: When the mouse pointer leaves the map, no coordinates are shown
- Line 63: The component is agnostic regarding its corner/position in the map.
Instead, it is expected that you wrap it with a
<div>
that has the desired position classes.
And here’s how you’d use it in a map:
import React from 'react';
import MouseCoordinates from './MouseCoordinates';
const GREECE_BOUNDS = [
[31.08, 14.26],
[44.91, 34.69],
];
function MyMap() {
return (
<MapContainer
bounds={GREECE_BOUNDS}
style={{ width: '100%', height: '100vh' }}
>
<TileLayer
url="https://{s}.tile.osm.org/{z}/{x}/{y}.png"
attribution='© <a href="https://osm.org/copyright">OpenStreetMap</a> contributors'
/>
<div className="leaflet-bottom leaflet-left"> <MouseCoordinates />
</div>
</MapContainer>
);
}
export default MyMap;
Things to note:
- Line 20: In this example, the coordinates are shown on the bottom-left corner of the map