Files
next-tjwater-drainage-frontend/features/workbench/hooks/use-map-interactions.ts
T

67 lines
2.1 KiB
TypeScript

"use client";
import type { Map as MapLibreMap, MapLayerMouseEvent } from "maplibre-gl";
import type { RefObject } from "react";
import { useEffect } from "react";
import type { DetailFeature } from "../types";
import { getFeatureId, toDetailFeature } from "../map/feature-adapter";
import { SOURCE_LAYERS } from "../map/sources";
const INTERACTIVE_LAYER_IDS = ["pipes-flow", "junctions"];
type UseMapInteractionsOptions = {
mapRef: RefObject<MapLibreMap | null>;
mapReady: boolean;
onSelectFeature: (feature: DetailFeature) => void;
};
export function useMapInteractions({
mapRef,
mapReady,
onSelectFeature
}: UseMapInteractionsOptions) {
useEffect(() => {
const map = mapRef.current;
if (!mapReady || !map) {
return;
}
const activeMap = map;
function handleMouseMove(event: MapLayerMouseEvent) {
activeMap.getCanvas().style.cursor = "pointer";
const feature = event.features?.[0];
if (!feature) {
return;
}
const id = getFeatureId(feature);
const layerId = feature.sourceLayer === SOURCE_LAYERS.pipes ? "pipes-hover" : "junctions-hover";
activeMap.setFilter(layerId, ["==", ["get", "id"], id]);
}
function handleMouseLeave() {
activeMap.getCanvas().style.cursor = "";
activeMap.setFilter("pipes-hover", ["==", ["get", "id"], ""]);
activeMap.setFilter("junctions-hover", ["==", ["get", "id"], ""]);
}
function handleClick(event: MapLayerMouseEvent) {
const feature = event.features?.[0];
if (feature) {
onSelectFeature(toDetailFeature(feature));
}
}
activeMap.on("mousemove", INTERACTIVE_LAYER_IDS, handleMouseMove);
activeMap.on("mouseleave", INTERACTIVE_LAYER_IDS, handleMouseLeave);
activeMap.on("click", INTERACTIVE_LAYER_IDS, handleClick);
return () => {
activeMap.off("mousemove", INTERACTIVE_LAYER_IDS, handleMouseMove);
activeMap.off("mouseleave", INTERACTIVE_LAYER_IDS, handleMouseLeave);
activeMap.off("click", INTERACTIVE_LAYER_IDS, handleClick);
};
}, [mapRef, mapReady, onSelectFeature]);
}