File size: 2,871 Bytes
394073d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18dfe1b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
394073d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import { useState, useEffect, useRef } from 'react'
import mapboxgl from 'mapbox-gl'
import 'mapbox-gl/dist/mapbox-gl.css'

export const useMap = (mapContainerRef, mapboxAccessToken, selectedLocation, analysisResult) => {
  const mapRef = useRef(null);
  const markerRef = useRef(null);
  const [mapInstance, setMapInstance] = useState(null);
  const [isMapLoaded, setIsMapLoaded] = useState(false);

  useEffect(() => {
    if (!mapContainerRef.current || !mapboxAccessToken || mapRef.current) {
      return;
    }

    mapboxgl.accessToken = mapboxAccessToken;

    mapRef.current = new mapboxgl.Map({
      container: mapContainerRef.current,
      style: 'mapbox://styles/mapbox/satellite-streets-v12',
      center: [20.0, 50.0],
      zoom: 4,
      projection: 'globe',
      attributionControl: false,
    });

    mapRef.current.on('load', () => {
      setIsMapLoaded(true);
      setMapInstance(mapRef.current);
    });

    mapRef.current.addControl(
      new mapboxgl.AttributionControl({
        compact: true
      }),
      'bottom-right'
    );

    return () => {
      mapRef.current?.remove();
      markerRef.current?.remove();
      mapRef.current = null;
      setMapInstance(null);
      setIsMapLoaded(false);
    }
  }, [mapContainerRef, mapboxAccessToken]);

  useEffect(() => {
    if (!isMapLoaded || !mapRef.current || !selectedLocation) {
      return;
    }

    const { lat, lng, isSearch } = selectedLocation;

    if (isSearch) {
      mapRef.current.flyTo({
        center: [lng, lat],
        zoom: 12,
        essential: true,
        duration: 2500
      });

      if (markerRef.current) {
        markerRef.current.remove();
        markerRef.current = null;
      }
    }
    else {
      if (markerRef.current) markerRef.current.remove();

      markerRef.current = new mapboxgl.Marker({ color: 'red' })
        .setLngLat([lng, lat])
        .addTo(mapRef.current);
    }

  }, [selectedLocation, isMapLoaded]);

  useEffect(() => {
    if (isMapLoaded && mapRef.current && analysisResult && selectedLocation) {
      const { lat, lng } = selectedLocation;

      mapRef.current.flyTo({
        center: [lng, lat],
        zoom: 12,
        essential: true,
        duration: 2500,
        curve: 1.2
      });
    }
  }, [analysisResult, isMapLoaded]);

  const handleZoomIn = () => {
    mapRef.current?.zoomIn({ duration: 300 });
  }

  const handleZoomOut = () => {
    mapRef.current?.zoomOut({ duration: 300 });
  }

  const handleFlyBackToAnalysis = () => {
    const target = analysisResult || selectedLocation;

    if (mapRef.current && target) {
      mapRef.current.flyTo({
        center: [target.lng || target.lon, target.lat],
        zoom: 12,
        essential: true,
        duration: 2500,
      });
    }
  }

  return { mapInstance, isMapLoaded, handleZoomIn, handleZoomOut, handleFlyBackToAnalysis };
}