import { Geolocation } from "ol"; import { unByKey } from "ol/Observable"; import { fromLonLat } from "ol/proj"; import { memo } from "preact/compat"; import { useEffect, useMemo } from "preact/hooks"; import GeolocationIcon from "../icons/Geolocation"; import IconButton from "../ui/IconButton"; import useI18n from "../utils/hooks/useI18n"; import useMapContext from "../utils/hooks/useMapContext"; import type { IconButtonProps } from "../ui/IconButton/IconButton"; export type GeolocationButtonProps = IconButtonProps; const TRACKING_ZOOM = 16; function GeolocationButton({ ...props }: GeolocationButtonProps) { const mapContext = useMapContext(); const { isTracking, map, setIsTracking } = mapContext; const { t } = useI18n(); const geolocation = useMemo(() => { return new Geolocation(); }, []); useEffect(() => { let keys = []; if (!map || !geolocation) { return; } keys = [ // First time we zoom and center on the position geolocation.once("change:position", (evt) => { const position = evt.target.getPosition(); if (evt.target.getPosition()) { map.getView().setZoom(TRACKING_ZOOM); map.getView().setCenter(fromLonLat(position, "EPSG:3857")); } }), // then we only center the map. geolocation.on("change:position", (evt) => { const position = evt.target.getPosition(); if (evt.target.getPosition()) { map.getView().setCenter(fromLonLat(position, "EPSG:3857")); } }), ]; return () => { unByKey(keys); }; }, [map, geolocation]); useEffect(() => { geolocation.setTracking(isTracking); }, [geolocation, isTracking]); return ( { setIsTracking(!isTracking); }} title={ isTracking ? t("geolocation_button_title_off") : t("geolocation_button_title_on") } {...props} > ); } export default memo(GeolocationButton);