67 lines
2.1 KiB
TypeScript
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]);
|
|
}
|