All files / custom-overlay/src useCustomOverlay.tsx

23.72% Statements 14/59
14.28% Branches 4/28
21.42% Functions 3/14
23.72% Lines 14/59

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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                                                                                                                          1x 1x 1x 1x 1x 1x 1x             1x 1x                         1x 1x 1x               1x 1x              
import { useState, useMemo, useEffect } from 'react';
import { createPortal } from 'react-dom';
import { useMapContext } from '@uiw/react-baidu-map-map';
import { useProperties, usePrevious } from '@uiw/react-baidu-map-utils';
import { CustomOverlayProps } from './';
 
function getCustomOverlay() {
  return class extends BMap.Overlay {
    public container: HTMLDivElement;
    public map!: BMap.Map;
    public paneName: keyof BMap.MapPanes;
    public position?: BMap.Point;
    public offset?: BMap.Size;
    constructor(elm: HTMLDivElement, position?: BMap.Point, paneName?: CustomOverlayProps['paneName']) {
      super();
      this.container = elm;
      this.paneName = paneName || 'markerPane';
      this.position = position;
    }
    public initialize: (map: BMap.Map) => HTMLElement = (map) => {
      const panes = map.getPanes();
      this.container.style.position = 'absolute';
      this.map = map;
      panes[this.paneName]!.appendChild(this.container);
      return this.container;
    };
    public draw = () => {
      if (this.position == null || this.map == null) {
        return;
      }
      const position = this.map.pointToOverlayPixel(this.position);
      const { width = 0, height = 0 } = this.offset || {};
 
      this.container.style.left = `${position.x + width}px`;
      this.container.style.top = `${position.y + height}px`;
    };
    public setOffset = (offset: BMap.Size) => {
      this.offset = offset;
      this.draw();
    };
    public setPosition = (position: BMap.Point) => {
      this.position = position;
      this.draw();
    };
    public setVisiable = (visiable: boolean) => {
      this.container.style.display = visiable ? 'block' : 'none';
    };
 
    public getPosition = () => {
      return this.position;
    };
 
    public setZIndex = (index: number) => {
      this.container.style.zIndex = index.toString();
    };
  };
}
 
export interface UseCustomOverlay extends CustomOverlayProps {}
 
export function useCustomOverlay(props = {} as UseCustomOverlay) {
  const { children, paneName, position } = props;
  const { map } = useMapContext();
  const [customOverlay, setCustomOverlay] = useState<BMap.Overlay>();
  const [div, setDiv] = useState<HTMLDivElement>();
  const [portal, setPortal] = useState<React.ReactPortal>();
  const [count, setCount] = useState(0);
  useEffect(() => {
    return () => {
      if (map && customOverlay) {
        map.removeOverlay(customOverlay);
      }
    };
  }, [customOverlay, map]);
  useMemo(() => {
    Iif (map && !portal && document) {
      const elm = document.createElement('div');
      const CustomOverlay = getCustomOverlay();
      const portalInstance = createPortal(children, elm);
      const CompOverlay = new CustomOverlay(elm, position, paneName);
      setCount(count + 1);
      setDiv(elm);
      map.addOverlay(CompOverlay);
      setPortal(portalInstance);
      setCustomOverlay(CompOverlay);
    }
  }, [children, count, map, paneName, portal, position]);
 
  const prevCount = usePrevious(count);
  useMemo(() => {
    Iif (map && div && children && count === prevCount) {
      const portalInstance = createPortal(children, div);
      setPortal(portalInstance);
      setCount(count + 1);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [children, customOverlay]);
 
  useProperties<BMap.Overlay, UseCustomOverlay>(customOverlay!, props, ['ZIndex', 'Offset', 'Position', 'Visiable']);
  return {
    portal,
    setPortal,
    customOverlay,
    setCustomOverlay,
  };
}