@wayz/react-gl
Version:
React Component for DeckGL, Base on AMap, Mapbox GL
177 lines (176 loc) • 7.61 kB
JavaScript
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);