nicecode-v2/packages/map/src/customOverlay/CustomOverlay.tsx

61 lines
1.4 KiB
TypeScript

// @ts-nocheck
import * as React from 'react';
import {useState, cloneElement} from 'react';
import {useControl} from 'react-map-gl';
import {createPortal} from 'react-dom';
import type { MapboxMap, IControl } from 'react-map-gl';
// Based on template in https://docs.mapbox.com/mapbox-gl-js/api/markers/#icontrol
class OverlayControl implements IControl {
_map: MapboxMap | undefined;
_container: HTMLElement | undefined;
_redraw: () => void;
constructor(redraw: () => void) {
this._redraw = redraw;
}
// @ts-ignore
onAdd(map) {
this._map = map;
map.on('move', this._redraw);
/* global document */
this._container = document.createElement('div');
this._redraw();
return this._container;
}
onRemove() {
this._container?.remove();
this._map?.off('move', this._redraw);
this._map = undefined;
}
getMap() {
return this._map;
}
getElement() {
return this._container;
}
}
/**
* A custom control that rerenders arbitrary React content whenever the camera changes
*/
function CustomOverlay(props: {children: React.ReactElement}) {
const [, setVersion] = useState(0);
const ctrl = useControl<OverlayControl>(() => {
const forceUpdate = () => setVersion(v => v + 1);
return new OverlayControl(forceUpdate);
});
const map = ctrl.getMap();
// @ts-ignore
return map && createPortal(cloneElement(props.children, {map}), ctrl.getElement());
}
export default React.memo(CustomOverlay);