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
|
import React, { useState, useEffect, useRef } from "react";
// @ts-ignore
import mapboxgl from '!mapbox-gl'; // eslint-disable-line import/no-webpack-loader-syntax
import {
MAPBOX_ACCESS_TOKEN,
IMAGE_COORDINATES,
IMAGES_BASE_URL
} from "./config";
import "mapbox-gl/dist/mapbox-gl.css";
interface MapProps {
slider: number,
images: string[],
}
export function Map({ slider, images }: MapProps) {
const mapContainer = useRef(null);
const map = useRef<mapboxgl.Map>(null);
const [lng, setLng] = useState(35);
const [lat, setLat] = useState(31.9);
const [zoom, setZoom] = useState(6.3);
const [loaded, setLoaded] = useState(false);
const prevImages = useRef(images).current;
const prevSlider = useRef(slider).current;
useEffect(() => {
if (map.current) return;
map.current = new mapboxgl.Map({
accessToken: MAPBOX_ACCESS_TOKEN,
container: mapContainer.current,
style: "mapbox://styles/mapbox/dark-v9",
center: [lng, lat],
zoom: zoom,
minZoom: 5,
maxZoom: 10,
hash: false,
});
map.current.on("style.load", () => {
setLoaded(true);
});
map.current.on("move", () => {
setLng(map.current.getCenter().lng.toFixed(4));
setLat(map.current.getCenter().lat.toFixed(4));
setZoom(map.current.getZoom().toFixed(2));
})
});
useEffect(() => {
if (!loaded) return;
// remove old layers
prevImages.forEach((img) => {
if (!images.includes(img)) {
map.current.removeLayer(`layer-${img}`);
map.current.removeSource(`source-${img}`);
}
});
// add new layers
images.forEach((img, i) => {
if (!prevImages.includes(img) && !map.current.getSource(`source-${img}`)) {
map.current.addSource(`source-${img}`, {
type: "image",
url: `${IMAGES_BASE_URL}/${img}`,
coordinates: IMAGE_COORDINATES
});
map.current.addLayer({
id: `layer-${img}`,
source: `source-${img}`,
type: "raster",
paint: {
"raster-opacity": 0,
"raster-opacity-transition": {
duration: 0
}
}
});
}
});
}, [loaded, prevImages, images]);
useEffect(() => {
if (!loaded) return;
images[prevSlider] && map.current.setPaintProperty(`layer-${images[prevSlider]}`, "raster-opacity", 0);
images[slider] && map.current.setPaintProperty(`layer-${images[slider]}`, "raster-opacity", 0.85);
}, [loaded, prevSlider, slider, images]);
return (
<div>
<div ref={mapContainer} className="map-container" style={{
height: "100vh",
width: "100vw"
}} />
</div>
);
}
|