170 lines
4.6 KiB
TypeScript
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;
|