UNPKG

@wayz/react-gl

Version:

React Component for DeckGL, Base on AMap, Mapbox GL

177 lines (176 loc) 7.61 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { useState, useRef, useCallback, useMemo, useEffect, memo, } from 'react'; import { DeckGL } from '@deck.gl/react'; import { AMap as StaticMap } from '@wayz/react-amap-gl'; import '@amap/amap-jsapi-types'; import { MapGLContext } from '../context/MapGLContext'; import { diffSetLayer, isFunction, quickSortLayerByZIndex } from '../utils'; const INITIAL_VIEW_STATE = { longitude: 116.405285, latitude: 39.904989, zoom: 3, }; const wrapperStyle = { zIndex: -1, position: 'absolute', }; const childrenWrapperStyle = { // position: 'absolute', zIndex: 1000, }; const deckToolTipWrapperStyle = { zIndex: 1, position: 'absolute', pointerEvents: 'none', top: 0, left: 0, }; const AMapGL = ({ children, MAP_ACCESS_TOKEN, mapStyle = 'light', glOptions, mapOptions, initialViewState = INITIAL_VIEW_STATE, onViewStateChange, onWebGLInitialized, debug, scaleControl, maxBounds, ...rest }) => { const [glContext, setGLContext] = useState(); const [layers, _setLayers] = useState([]); const [viewState, _setViewState] = useState(() => { if (initialViewState.altitude === 0) { throw new Error('initialViewState.altitude 不能设置为0'); } return initialViewState; }); const [map, setMap] = useState(); const [hoverInfo, _setHoverInfo] = useState(); const deckRef = useRef(null); const viewStateRef = useRef(initialViewState); // 控制台输入, layers的状态 debug && console.info(`layers: `, layers); // 添加图层 const _addLayer = useCallback((layer) => { // 合并数组, 并按照zIndex排序 _setLayers((layers) => { return quickSortLayerByZIndex([...layers, ...(Array.isArray(layer) ? layer : [layer])]); }); }, []); // 移除图层 const _removeLayer = useCallback((layer) => { // 求差集 _setLayers((layers) => { return diffSetLayer(layers, Array.isArray(layer) ? layer : [layer]); }); }, []); // 设置高德地图状态 const setterMap = useMemo(() => ({ zoom(zoom) { map === null || map === void 0 ? void 0 : map.setZoom(zoom + 1); }, zooms(minZoom, maxZoom) { map === null || map === void 0 ? void 0 : map.setZooms([minZoom, maxZoom]); }, rotation(bearing) { map === null || map === void 0 ? void 0 : map.setRotation((360 - bearing) % 360); }, center(center) { map === null || map === void 0 ? void 0 : map.setCenter(center); }, pitch(pitch) { map === null || map === void 0 ? void 0 : map.setPitch(pitch); }, }), [map]); // 同步高德viewState const setAMapViewState = useCallback((viewState) => { const { pitch = 0, longitude = 116.397428, latitude = 39.90923, zoom = 3, maxZoom = 22, minZoom = 0, bearing = 0, } = viewState; const center = [longitude, latitude]; setterMap.center(center); setterMap.zoom(zoom); setterMap.rotation(bearing); setterMap.zooms(minZoom, maxZoom); setterMap.pitch(pitch); }, [setterMap]); // 获取viewState const getViewState = useCallback(() => viewStateRef.current, []); // 设置viewState const setViewState = useCallback((viewState) => { // debugger _setViewState((vs) => { const _viewState = Object.assign({}, vs, isFunction(viewState) ? viewState(vs) : viewState); // 设置 maxBounds if (maxBounds) { _viewState.longitude = Math.min(maxBounds[2], Math.max(maxBounds[0], _viewState.longitude)); _viewState.latitude = Math.min(maxBounds[3], Math.max(maxBounds[1], _viewState.latitude)); } viewStateRef.current = _viewState; // viewState改变时, 同步修改地图view setAMapViewState(_viewState); onViewStateChange === null || onViewStateChange === void 0 ? void 0 : onViewStateChange(_viewState); return _viewState; }); }, [onViewStateChange, setAMapViewState, maxBounds]); // 设置hoverInfo const setHoverInfo = useCallback((info) => { _setHoverInfo(info); }, []); // viewState changes const handleViewStateChange = useCallback(({ viewState }) => { setViewState(viewState); }, [setViewState]); // get amap instance const onMapLoad = useCallback((ins) => setMap(ins), []); const handleWebGLInitialized = useCallback((gl) => { setGLContext(gl); onWebGLInitialized === null || onWebGLInitialized === void 0 ? void 0 : onWebGLInitialized(gl); }, [setGLContext, onWebGLInitialized]); // amap plugins const plugins = useMemo(() => { const plugins = []; if (scaleControl === null || scaleControl === void 0 ? void 0 : scaleControl.show) { plugins.push('AMap.Scale'); } return plugins; }, [scaleControl]); // glOptions const glOpts = useMemo(() => { return glOptions ? { ...glOptions, /* To render vector tile polygons correctly */ stencil: true } : { stencil: true, preserveDrawingBuffer: true }; }, [glOptions]); // mapOptions const mapOpts = useMemo(() => { return mapOptions ? { ...mapOptions, /* close animate */ animateEnable: false, viewMode: '3D', jogEnable: false, } : { animateEnable: false, viewMode: '3D', jogEnable: false }; }, [mapOptions]); const MapGLContextValue = useMemo(() => { return { _addLayer, _removeLayer, getViewState, setViewState, setHoverInfo, deck: deckRef.current, map, }; }, [_addLayer, _removeLayer, getViewState, setViewState, setHoverInfo, deckRef.current, map]); useEffect(() => { if (!map) return; if ((scaleControl === null || scaleControl === void 0 ? void 0 : scaleControl.show) && window.AMap.Scale) { // 在图面添加比例尺控件,展示地图在当前层级和纬度下的比例尺 map.addControl(new window.AMap.Scale()); } }, [scaleControl, map]); useEffect(() => { // 初始化同步一次地图状态 setAMapViewState(viewState); }, [map, setAMapViewState]); return (_jsxs(_Fragment, { children: [_jsxs(DeckGL, { ...rest, layers: layers, ref: deckRef, // initialViewState={initialViewState} viewState: viewState, controller: true, // ContextProvider={MapContext.Provider} onWebGLInitialized: handleWebGLInitialized, onViewStateChange: handleViewStateChange, glOptions: glOpts, children: [glContext && (_jsx(StaticMap, { style: wrapperStyle, onLoad: onMapLoad, MAP_ACCESS_TOKEN: MAP_ACCESS_TOKEN, mapOption: mapOpts, mapStyle: mapStyle, plugins: plugins })), hoverInfo && hoverInfo.object && (_jsx("div", { style: { ...deckToolTipWrapperStyle, left: hoverInfo.x, top: hoverInfo.y, }, children: hoverInfo.html }))] }), _jsx(MapGLContext.Provider, { value: MapGLContextValue, children: _jsx("div", { className: "children-wrapper", style: childrenWrapperStyle, children: children }) })] })); }; export default memo(AMapGL);