Displaying a Pop-up on Hover for Vector Features

25 views
Skip to first unread message
Assigned to stefan...@geosolutionsgroup.com by lorenzo...@geosolutionsgroup.com

Mabuela Ngulube

unread,
Feb 19, 2025, 6:48:41 AMFeb 19
to mapstore-developers

Hi,

I want to create a pop-up when a user hovers over a vector feature. Is there a built-in solution for this? If not, how can I convert the mouse position from pixels to map coordinates (similar to how coordinates are determined when a user clicks on a feature)?

Mabuela Ngulube

unread,
Feb 24, 2025, 6:01:27 AMFeb 24
to mapstore-developers
Hi everyone,

For anyone who might want a solution for this in the future, I managed to create a hook that returns a feature that is hovered on and its pixel coordinates. All one has to do is create a pop-up using this info.

//useMouseTracker.jsx (tracks mouse movement)
import { useState, useEffect } from "react";

const useMouseTracker = () => {
const [pixelCoordinates, setPixelCoordinates] = useState({ x: 0, y: 0 });

useEffect(() => {
const handleMouseMove = (event) => {
setPixelCoordinates({ x: event.clientX, y: event.clientY });
};

window.addEventListener("mousemove", handleMouseMove);

return () => {
window.removeEventListener("mousemove", handleMouseMove);
};
}, []);

return pixelCoordinates;
};

export default useMouseTracker;




//useHoverOnMarker.jsx (returns coordinate hovered on and pixel coordinate)
import { useState, useEffect } from "react";
import useMouseTracker from "./useMouseTracker";
import { reproject } from "@mapstore/utils/CoordinatesUtils";

const useHoverOnFeature = (map, geoJson, hoverRadius = 10) => {
const [closestFeature, setClosestFeature] = useState(null);
const [closestFeaturePixel, setClosestFeaturePixel] = useState(null);
const mouseCoords = useMouseTracker(); // Get pixel coordinates of the mouse

useEffect(() => {
if (!map || !geoJson || !geoJson.features || geoJson.features.length === 0) return;

let minDistance = Infinity;
let nearestFeature = null;
let nearestPixelCoords = null;

geoJson.features.forEach((feature) => {
const { coordinates } = feature.geometry;
if (!coordinates || coordinates.length < 2) return;

const projectedCoords = reproject(
[coordinates[0], coordinates[1]],
"EPSG:4326",
"EPSG:900913"
);

const featurePixelCoords = map.getPixelFromCoordinate([
projectedCoords.x,
projectedCoords.y,
]);

if (!featurePixelCoords) return;

const distance = Math.sqrt(
Math.pow(mouseCoords.x - featurePixelCoords[0], 2) +
Math.pow(mouseCoords.y - featurePixelCoords[1], 2)
);

if (distance <= hoverRadius && distance < minDistance) {
minDistance = distance;
nearestFeature = feature;
nearestPixelCoords = featurePixelCoords;
}
});

setClosestFeature(nearestFeature);
setClosestFeaturePixel(nearestPixelCoords);
}, [map, geoJson, mouseCoords, hoverRadius]);

return { closestFeature, closestFeaturePixel };
};

export default useHoverOnFeature;


Mabuela Ngulube

unread,
Feb 24, 2025, 6:32:08 AMFeb 24
to mapstore-developers
By default, map is passed as a prop for plugins. Below is a use-case example.

const TemplatePlugin = ({ map, mapType }) => {
const [markerGeoCoords, setMarkerGeoCoords] = useState([]);

const mapLayers = useSelector((state) => state.layers);
const closest = useHoverOnMarker(map, markerGeoCoords);


useEffect(() => {
const estuaries = mapLayers.flat.find(
(layer) => layer.title === "Estuary Markers"
);

if (estuaries) {
setMarkerGeoCoords(estuaries);
}
}, [mapLayers]);


On Wednesday, February 19, 2025 at 1:48:41 PM UTC+2 Mabuela Ngulube wrote:

stefano.bovio

unread,
Feb 27, 2025, 4:45:42 AMFeb 27
to mapstore-developers
Hi,

Thanks for sharing your solution!
Just a question is this working with OpenLayers library (2D view in MapStore)?

Thanks again,
Stefano


Mabuela Ngulube

unread,
Feb 27, 2025, 7:05:41 AMFeb 27
to mapstore-...@googlegroups.com
Hi Stefano

Yes, it does.

--
You received this message because you are subscribed to the Google Groups "mapstore-developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mapstore-develo...@googlegroups.com.
To view this discussion, visit https://groups.google.com/d/msgid/mapstore-developers/4173fe17-0ab4-4644-a610-b32378f8c365n%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages