nicecode-v2/packages/map/src/MapBox.tsx

170 lines
4.6 KiB
TypeScript

import 'mapbox-gl/dist/mapbox-gl.css';
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
import Map from 'react-map-gl';
import { CSSProperties } from "react";
import { MapboxMap, MapRef, MapStyle } from "react-map-gl";
import classnames from 'classnames'
import Tools, { ToolsProps } from './components/tools'
import DrawControl, { DrawControlProps, DrawControlRefProps } from './components/drawControl';
import { MAP_CENTER, defaultMapConfig } from './utils/constants';
import './index.less';
import mapboxDrawStyle from './utils/drawStyle';
import Marker from './components/marker';
const componentName = 'zhst-map'
export interface IMarkerData {
key: string;
title: string;
population: string;
status: string;
latitude: number;
longitude: number;
}
export interface MapProps extends Partial<MapboxMap> {
mapboxAccessToken?: string; //token
markerData?: IMarkerData[]
minZoom?: number; //最小层级
maxZoom?: number; //最大层级
mapStyle?: MapStyle; //地图样式
height?: number | string;
width?: string | number;
mapRef?: MapRef;
style?: CSSProperties;
children?: JSX.Element | JSX.Element[] | Array<JSX.Element | undefined>;
mapCenter?: {
longitude: number, latitude: number
}
draw?: boolean;
buttonList?: ToolsProps['buttonList']
onLoad?: (e: mapboxgl.MapboxEvent<undefined>) => void;
onDrawCreate?: (e: { features: object[], [key: string]: any }) => void;
onDrawUpdate?: (e: { features: object[], [key: string]: any }) => void;
onDrawDelete?: (e: { features: object[], [key: string]: any }) => void;
}
export interface MapRefProps {
}
const MapBox = forwardRef<MapRefProps, MapProps>((props, ref) => {
const {
style = {},
children,
mapCenter = MAP_CENTER,
height = 600,
width = '100%',
draw,
markerData = [],
buttonList = [
{
label: '圆形框选',
key: 'circle',
icon: 'icon-yuan',
onClick: () => drawControlRef.current?.drawer?.changeMode?.('draw_circle')
},
{
label: '矩形框选',
key: 'rect',
icon: 'icon-fang',
onClick: () => drawControlRef.current?.drawer?.changeMode?.('draw_rect')
},
{
label: '多边形框选',
key: 'more',
icon: 'icon-duobianxing',
onClick: () => drawControlRef.current?.drawer?.changeMode?.('draw_polygon')
},
{
label: '路径框选',
key: 'path',
icon: 'icon-lujingkuangxuannor',
onClick: () => drawControlRef.current?.drawer?.changeMode?.('draw_line_string')
},
{
label: '清除',
key: 'clear',
icon: 'icon-gongjuxiangguanbi',
onClick: () => drawControlRef.current?.drawer?.deleteAll()
}
],
onLoad,
onDrawCreate,
onDrawUpdate,
onDrawDelete,
...others
} = props || {};
const mapRef = useRef<MapRef>(null)
const drawControlRef = useRef<DrawControlRefProps>(null)
// 默认绘制配置
const [drawConfig] = useState<DrawControlProps>({
displayControlsDefault: false,
position: 'top-left',
styles: mapboxDrawStyle,
// Select which mapbox-gl-draw control buttons to add to the map.
controls: {
polygon: true,
trash: true
},
// The user does not have to click the polygon control button first.
defaultMode: 'draw_polygon',
})
const initMarker = useMemo(
() => {
return markerData.map((_item, index) => (
<Marker
key={_item.key || index}
latitude={_item.latitude}
longitude={_item.longitude}
/>
))
},
[markerData]
);
useImperativeHandle(ref, () => ({
mapRef: mapRef.current,
drawer: drawControlRef.current?.drawer,
}))
return (
//@ts-ignore
<div className={classnames(`${componentName}`)}>
<Tools
buttonList={buttonList}
/>
{/* @ts-ignore */}
<Map
ref={mapRef}
{...defaultMapConfig}
initialViewState={{ ...mapCenter }}
onLoad={onLoad}
style={{ width: width, height: height, ...style }}
{...others}
>
{initMarker}
{/* <CustomOverlay
>
<Button>定制图层</Button>
</CustomOverlay> */}
{/* ---------------绘制图层--------------------- */}
{draw && (
<DrawControl
ref={drawControlRef}
onCreate={onDrawCreate}
onUpdate={onDrawUpdate}
onDelete={onDrawDelete}
{...drawConfig}
/>
)}
{children}
</Map>
</div>
);
});
export default MapBox;