94 lines
2.9 KiB
TypeScript
94 lines
2.9 KiB
TypeScript
"use client"
|
|
|
|
import { IBaseLayerProps } from "@/app/_utils/types/map"
|
|
import { useEffect } from "react"
|
|
|
|
|
|
export default function FlyToHandler({ map }: Pick<IBaseLayerProps, "map">) {
|
|
useEffect(() => {
|
|
if (!map) return
|
|
|
|
const handleFlyToEvent = (e: CustomEvent) => {
|
|
if (!map || !e.detail) return
|
|
|
|
const { longitude, latitude, zoom, bearing, pitch, duration } = e.detail
|
|
|
|
map.flyTo({
|
|
center: [longitude, latitude],
|
|
zoom: zoom || 15,
|
|
bearing: bearing || 0,
|
|
pitch: pitch || 45,
|
|
duration: duration || 2000,
|
|
})
|
|
|
|
// Add a highlight or pulse effect to the target incident
|
|
if (map.getLayer("target-incident-highlight")) {
|
|
map.removeLayer("target-incident-highlight")
|
|
}
|
|
|
|
if (map.getSource("target-incident-highlight")) {
|
|
map.removeSource("target-incident-highlight")
|
|
}
|
|
|
|
map.addSource("target-incident-highlight", {
|
|
type: "geojson",
|
|
data: {
|
|
type: "Feature",
|
|
geometry: {
|
|
type: "Point",
|
|
coordinates: [longitude, latitude],
|
|
},
|
|
properties: {},
|
|
},
|
|
})
|
|
|
|
map.addLayer({
|
|
id: "target-incident-highlight",
|
|
source: "target-incident-highlight",
|
|
type: "circle",
|
|
paint: {
|
|
"circle-radius": ["interpolate", ["linear"], ["zoom"], 10, 10, 15, 15, 20, 20],
|
|
"circle-color": "#ff0000",
|
|
"circle-opacity": 0.7,
|
|
"circle-stroke-width": 2,
|
|
"circle-stroke-color": "#ffffff",
|
|
},
|
|
})
|
|
|
|
// Add a pulsing effect using animations
|
|
let size = 10
|
|
const animatePulse = () => {
|
|
if (!map || !map.getLayer("target-incident-highlight")) return
|
|
|
|
size = (size % 20) + 1
|
|
|
|
map.setPaintProperty("target-incident-highlight", "circle-radius", [
|
|
"interpolate",
|
|
["linear"],
|
|
["zoom"],
|
|
10,
|
|
size,
|
|
15,
|
|
size * 1.5,
|
|
20,
|
|
size * 2,
|
|
])
|
|
|
|
requestAnimationFrame(animatePulse)
|
|
}
|
|
|
|
requestAnimationFrame(animatePulse)
|
|
}
|
|
|
|
map.getCanvas().addEventListener("mapbox_fly_to", handleFlyToEvent as EventListener)
|
|
|
|
return () => {
|
|
if (map && map.getCanvas()) {
|
|
map.getCanvas().removeEventListener("mapbox_fly_to", handleFlyToEvent as EventListener)
|
|
}
|
|
}
|
|
}, [map])
|
|
|
|
return null
|
|
}
|