All files / map/src index.tsx

52% Statements 13/25
28.57% Branches 6/21
25% Functions 2/8
60% Lines 12/20

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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178                                                                                                                                                                                                                                                                1x           1x 1x 1x 1x         1x   1x   1x   1x 1x 1x         1x                                            
/// <reference types="@uiw/react-baidu-map-types" />
import React, {
  FC,
  PropsWithChildren,
  useRef,
  useEffect,
  useImperativeHandle,
  useReducer,
  useMemo,
  CSSProperties,
} from 'react';
import { useMap } from './useMap';
import { Context, reducer, initialState } from './context';
 
export * from './useMap';
export * from './context';
 
export interface Control {
  Control: BMap.Control;
  NavigationControl: BMap.NavigationControlOptions;
  OverviewMapControl: BMap.OverviewMapControlOptions;
  ScaleControl: BMap.ScaleControlOptions;
  MapTypeControl: BMap.MapTypeControlOptions;
  CopyrightControl: BMap.CopyrightControlOptions;
  GeolocationControl: BMap.GeolocationControlOptions;
}
 
export type ControlOptions =
  | {
      name: keyof Control;
      options?: (bmap: typeof BMap, map: BMap.Map) => void;
      control?(bmap: typeof BMap, map: BMap.Map): BMap.Control;
    }
  | {
      name: keyof Control;
      options?: Control[keyof Control];
      control?(bmap: typeof BMap, map: BMap.Map): BMap.Control;
    };
 
export type ControlOptionsAll = keyof Control | ControlOptions;
 
export interface MapProps extends BMap.MapOptions, BMap.MapEvents {
  className?: React.HTMLAttributes<HTMLDivElement>['className'];
  style?: React.HTMLAttributes<HTMLDivElement>['style'];
  /**
   * 指定的容器
   */
  container?: HTMLDivElement | null | undefined;
  /**
   * 百度地图上负责与地图交互的UI元素称为控件。
   */
  widget?: (ControlOptionsAll | ControlOptions)[];
  /**
   * 缩放等级
   */
  zoom?: number;
  /**
   * 定位, 可使用如 `上海市` 的地区字符串,
   * 也可以使用对象如 `{lng: 121.424333, lat: 31.228604}` 表示经纬度
   */
  center?: string | BMap.Point;
  /**
   * IP定位获取当前城市,进行自动定位
   */
  autoLocalCity?: boolean;
  /** 设置地图默认的鼠标指针样式。参数cursor应符合CSS的cursor属性规范 */
  defaultCursor?: CSSProperties['cursor'];
  /**
   * 启用地图拖拽,默认启用
   */
  enableDragging?: boolean;
  /**
   * 启用滚轮放大缩小,默认禁用
   */
  enableScrollWheelZoom?: boolean;
  /**
   * 启用双击放大,默认启用
   */
  enableDoubleClickZoom?: boolean;
  /**
   * 启用地图惯性拖拽,默认禁用
   */
  enableInertialDragging?: boolean;
  /**
   * 启用连续缩放效果,默认禁用
   */
  enableContinuousZoom?: boolean;
  /**
   * 启用双指操作缩放,默认启用
   */
  enablePinchToZoom?: boolean;
  /**
   * 启用键盘操作,默认禁用。键盘的上、下、左、右键可连续移动地图。同时按下其中两个键可使地图进行对角移动。
   * PgUp、PgDn、Home和End键会使地图平移其1/2的大小。+、-键会使地图放大或缩小一级
   */
  enableKeyboard?: boolean;
  /**
   * 设置地图个性化样式V2版本,仅支持现代浏览器(支持Canvas)
   */
  mapStyleV2?: BMap.MapStyleV2;
  /**
   * 设置地图城市,注意当地图初始化时的类型设置为 `BMAP_NORMAL_MAP` 时,
   * 需要在调用 `centerAndZoom` 之前调用此方法设置地图所在城市。
   * 例如:
   * @example
   *
   * ```js
   * var map = new BMap.Map(“container”, { mapType: BMAP_NORMAL_MAP });
   * map.setCurrentCity(“北京市”);
   * map.centerAndZoom(new BMap.Point(116.404, 39.915), 18);
   * ```
   *
   * 注意:初始化的坐标应与您设置的城市对应,否则地图将无法正常显示。
   */
  currentCity?: string;
  /**
   * 将全景实例与Map类进行绑定
   */
  panorama?: BMap.Panorama;
 
  viewport?: (view: Array<BMap.Point> | BMap.Viewport, viewportOptions: BMap.ViewportOptions) => void;
  children?: RenderProps['children'];
}
 
export type RenderProps =
  | { children?: (data: { BMap: typeof BMap; map: BMap.Map; container?: HTMLDivElement | null }) => React.ReactNode }
  | { children?: React.ReactNode };
 
export const Provider: FC<PropsWithChildren<RenderProps>> = (props) => {
  const [state, dispatch] = useReducer(reducer, initialState);
  return <Context.Provider value={{ state, dispatch }}>{props.children}</Context.Provider>;
};
export type MapRefs = MapProps & { map?: BMap.Map; BMap?: typeof BMap; container?: HTMLDivElement | null };
export default React.forwardRef<MapRefs, MapProps & RenderProps>(({ className, style, children, ...props }, ref) => {
  const [state, dispatch] = useReducer(reducer, initialState);
  window.BMap = window.BMap || window.BMapGL;
  const elmRef = useRef<HTMLDivElement>(null);
  const { setContainer, container, setCenter, setAutoLocalCity, map } = useMap({
    container: elmRef.current,
    ...props,
  });
  // eslint-disable-next-line react-hooks/exhaustive-deps
  useEffect(() => setContainer(elmRef.current), [elmRef.current]);
  // eslint-disable-next-line react-hooks/exhaustive-deps
  useMemo(() => props.center && setCenter(props.center!), [props.center]);
  // eslint-disable-next-line react-hooks/exhaustive-deps
  useEffect(() => setAutoLocalCity(props.autoLocalCity!), [props.autoLocalCity]);
  // eslint-disable-next-line react-hooks/exhaustive-deps
  useImperativeHandle(ref, () => ({ ...props, map, BMap, container: elmRef.current }), [map]);
  const chields = typeof children === 'function' ? [children] : React.Children.toArray(children);
  useEffect(() => {
    if (map) {
      dispatch({ map, container: elmRef.current, BMap });
    }
  }, [map]);
  return (
    <Context.Provider value={{ state, dispatch }}>
      <div ref={elmRef} className={className} style={{ fontSize: 1, height: '100%', ...style }} />
      {BMap && map && typeof children === 'function' && children({ BMap, map, container })}
      {BMap &&
        map &&
        chields.map((child, key) => {
          if (!React.isValidElement(child)) return null;
          if (child.type && typeof child.type === 'string') {
            return React.cloneElement(child, { key });
          }
          return React.cloneElement(child, {
            ...child.props,
            BMap,
            map,
            container,
            key,
          });
        })}
    </Context.Provider>
  );
});