Skip to content

Commit

Permalink
migration from Mapbox GL to MapLibre GL
Browse files Browse the repository at this point in the history
  • Loading branch information
davidsingal committed Feb 22, 2024
1 parent 2a85722 commit 66111da
Show file tree
Hide file tree
Showing 18 changed files with 6,297 additions and 157 deletions.
4 changes: 2 additions & 2 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"jsona": "1.9.2",
"lodash-es": "4.17.21",
"lottie-react": "2.4.0",
"mapbox-gl": "2.13.0",
"maplibre-gl": "3.6.2",
"next": "13.5.5",
"next-auth": "4.19.2",
"pino": "8.1.0",
Expand All @@ -64,7 +64,7 @@
"react-dropzone": "14.2.2",
"react-hook-form": "7.43.1",
"react-hot-toast": "2.2.0",
"react-map-gl": "7.0.23",
"react-map-gl": "7.1.7",
"react-range": "1.8.14",
"react-redux": "8.0.2",
"recharts": "2.9.0",
Expand Down
94 changes: 10 additions & 84 deletions client/src/components/map/component.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,13 @@
import React, { useEffect, useState, useCallback } from 'react';
import ReactMapGL, { useMap } from 'react-map-gl';
import ReactMapGL, { useMap } from 'react-map-gl/maplibre';
import { useDebounce } from 'rooks';

import { DEFAULT_VIEW_STATE, MAP_STYLES } from './constants';
import { INITIAL_VIEW_STATE, MAP_STYLES } from './constants';

import type { ViewState, ViewStateChangeEvent, MapboxEvent } from 'react-map-gl';
import type { ViewState, ViewStateChangeEvent } from 'react-map-gl/maplibre';
import type { FC } from 'react';
import type { CustomMapProps } from './types';

const MAPBOX_API_TOKEN = process.env.NEXT_PUBLIC_MAPBOX_API_TOKEN;

export const INITIAL_VIEW_STATE: ViewState = {
longitude: 0,
latitude: 0,
zoom: 2,
pitch: 0,
bearing: 0,
padding: null,
};

export const Map: FC<CustomMapProps> = ({
id = 'default',
mapStyle = 'terrain',
Expand All @@ -33,7 +22,9 @@ export const Map: FC<CustomMapProps> = ({
doubleClickZoom,
onLoad,
sidebarCollapsed = false,
...mapboxProps
touchZoomRotate, // not supported in MapLibre
touchPitch, // not supported in MapLibre
...otherMapProps
}: CustomMapProps) => {
/**
* REFS
Expand All @@ -45,30 +36,11 @@ export const Map: FC<CustomMapProps> = ({
*/
const [localViewState, setLocalViewState] = useState<Partial<ViewState>>(
!initialViewState && {
...DEFAULT_VIEW_STATE,
...INITIAL_VIEW_STATE,
...viewState,
},
);
const onMapViewStateChangeDebounced = useDebounce(onMapViewStateChange, 150);
const [isFlying, setFlying] = useState(false);

/**
* CALLBACKS
*/
const handleFitBounds = useCallback(() => {
const { bbox, options } = bounds;

// enabling fly mode avoids the map to be interrupted during the bounds transition
setFlying(true);

mapRef.fitBounds(
[
[bbox[0], bbox[1]],
[bbox[2], bbox[3]],
],
options,
);
}, [bounds, mapRef]);

const handleMapMove = useCallback(
({ viewState: _viewState }: ViewStateChangeEvent) => {
Expand All @@ -84,69 +56,23 @@ export const Map: FC<CustomMapProps> = ({
// Cancel last timeout if a new one it triggered
clearTimeout(resizeWhenCollapse);

// Trigger the map resize if the sibe bar has been collapsed. There is no need to resize if the sidebar has been expanded because the container will hide the excess width
// Trigger the map resize if the sidebar has been collapsed. There is no need to resize if the sidebar has been expanded because the container will hide the excess width
if (sidebarCollapsed) {
resizeWhenCollapse = setTimeout(() => {
mapRef?.resize();
}, 150);
}
}, [sidebarCollapsed, mapRef]);

useEffect(() => {
if (mapRef && bounds) {
handleFitBounds();
}
}, [mapRef, bounds, handleFitBounds]);

useEffect(() => {
setLocalViewState((prevViewState) => ({
...prevViewState,
...viewState,
}));
}, [viewState]);

useEffect(() => {
if (!bounds) return undefined;

const { options } = bounds;
const animationDuration = options?.duration || 0;
let timeoutId: number = null;

if (isFlying) {
timeoutId = window.setTimeout(() => {
setFlying(false);
}, animationDuration);
}

return () => {
if (timeoutId) {
window.clearInterval(timeoutId);
}
};
}, [bounds, isFlying]);

const handleMapLoad = useCallback(
(evt: MapboxEvent) => {
if (onLoad) onLoad(evt);
},
[onLoad],
);

return (
<ReactMapGL
id={id}
mapStyle={MAP_STYLES[mapStyle]}
initialViewState={initialViewState}
mapboxAccessToken={MAPBOX_API_TOKEN}
dragPan={!isFlying && dragPan}
dragRotate={!isFlying && dragRotate}
scrollZoom={!isFlying && scrollZoom}
doubleClickZoom={!isFlying && doubleClickZoom}
onMove={handleMapMove}
onLoad={handleMapLoad}
className="-z-10"
{...mapboxProps}
{...otherMapProps}
{...localViewState}
attributionControl
>
{!!mapRef && children(mapRef.getMap())}
</ReactMapGL>
Expand Down
6 changes: 3 additions & 3 deletions client/src/components/map/constants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DefaultMapStyle from './styles/map-style.json';
import SatelliteMapStyle from './styles/map-style-satellite.json';
import DefaultMapStyle from './styles/map-style-maplibre.json';
import SatelliteMapStyle from './styles/map-style-satellite-maplibre.json';

import type { ViewState, MapProps } from 'react-map-gl';
import type { ViewState, MapProps } from 'react-map-gl/maplibre';

export const DEFAULT_VIEW_STATE: Partial<ViewState> = {
zoom: 2,
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/map/controls/zoom/component.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useCallback } from 'react';
import cx from 'classnames';
import { useMap } from 'react-map-gl';
import { useMap } from 'react-map-gl/maplibre';
import { MinusIcon, PlusIcon } from '@heroicons/react/solid';

import type { MouseEventHandler } from 'react';
Expand Down
1 change: 1 addition & 0 deletions client/src/components/map/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default } from './component';
export * from './component';
export * from './constants';
2 changes: 1 addition & 1 deletion client/src/components/map/layer-manager/provider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createContext, useCallback, useContext, useMemo } from 'react';
import { useControl } from 'react-map-gl';
import { useControl } from 'react-map-gl/maplibre';
import { MapboxOverlay } from '@deck.gl/mapbox/typed';

import type { MapboxOverlayProps } from '@deck.gl/mapbox/typed';
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/map/layers/deck/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect } from 'react';
import { Layer } from 'react-map-gl';
import { Layer } from 'react-map-gl/maplibre';

import { useMapboxOverlayContext } from 'components/map/layer-manager/provider';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,43 @@ import { useMemo } from 'react';

import { getTiler } from './utils';

import type { AnyLayer, AnySourceData } from 'mapbox-gl';
import type { RasterLayerSpecification, RasterSourceSpecification } from 'maplibre-gl';
import type { LayerSettings, LayerProps } from 'components/map/layers/types';

export function useSource({
id,
// id,
tilerUrl,
defaultTilerParams,
}: LayerProps<LayerSettings>): AnySourceData {
}: LayerProps<LayerSettings>): RasterSourceSpecification {
const tiler = useMemo(
() => getTiler(tilerUrl, defaultTilerParams),
[tilerUrl, defaultTilerParams],
);

return {
id: `${id}-source`,
// id: `${id}-source`,
type: 'raster',
tiles: [tiler],
};
}

export function useLayer({ id, settings = {} }: LayerProps<LayerSettings>): AnyLayer {
export function useLayer({
id,
settings = {},
}: LayerProps<LayerSettings>): RasterLayerSpecification {
const visibility = settings.visibility ?? true;
const layer = useMemo<AnyLayer>(() => {
const layer = useMemo<RasterLayerSpecification>((): RasterLayerSpecification => {
return {
id,
type: 'raster',
source: `${id}-source`,
paint: {
'raster-opacity': settings.opacity ?? 1,
},
layout: {
visibility: visibility ? 'visible' : 'none',
},
} satisfies AnyLayer;
} satisfies RasterLayerSpecification;
}, [id, settings, visibility]);

return layer;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Source, Layer } from 'react-map-gl';
import { Source, Layer } from 'react-map-gl/maplibre';

import { useLayer, useSource } from './hooks';

Expand Down
Loading

0 comments on commit 66111da

Please sign in to comment.