mcfxkh-Web/src/views/Home/MapCtrl/index.js

172 lines
4.7 KiB
JavaScript
Raw Normal View History

2025-05-19 14:26:18 +08:00
import React, { useEffect, useReducer, useRef } from 'react';
import config from '../../../config';
import { useDispatch, useSelector } from 'react-redux';
import { getLayerVisible, getLayerSetting, getCameraTarget } from '../../../models/map/selectors';
import useRefresh from '../../../utils/useRefresh';
import LayerMgr from './mapstyle/layermgr';
import FeatureTip from './FeatureTip';
import FeaturePops from './FeaturePops';
import Markers from './markers/Markers';
const mapboxgl = window.mapboxgl;
mapboxgl.accessToken = 'pk.eyJ1IjoiaW5ob25vb3IiLCJhIjoiQzgzSmFadyJ9.jQDKFw6z_HrtBzu8hY415g';
export default function MapCtrl({ initParams, onLoad }) {
initParams = initParams || {};
const mapContainerRef = useRef();
const mapRef = useRef(); // 别问为什么不用state而用ref加上底下一行的刷新
const [refresh, forceRender] = useReducer(s => s + 1, 0);
const dispatch = useDispatch();
const layerVisible = useSelector(getLayerVisible);
const layerSetting = useSelector(getLayerSetting);
const tick = useRefresh(60 * 1000);
const layermgrRef = useRef(new LayerMgr());
const cameraTarget = useSelector(getCameraTarget);
// 图层显示隐藏,显示设置
useEffect(() => {
const mapCtrl = mapRef.current;
if (!mapCtrl) {
return;
}
const layers = layermgrRef.current.getLayers();
for (const layerInfo of layers) {
const visible = layerVisible[layerInfo.getName()];
if (visible) {
layerInfo.setVisible(mapCtrl, true);
layerInfo.setLayerSettings(mapCtrl, layerSetting);
} else {
layerInfo.setVisible(mapCtrl, false);
if (layerInfo.isVisible()) {
layerInfo.setLayerSettings(mapCtrl, layerSetting);
}
}
}
}, [refresh, layerVisible, layerSetting]);
// 定时刷新图层
useEffect(() => {
const mapCtrl = mapRef.current;
if (!mapCtrl) {
return;
}
for (const key in layerVisible) {
const layerInfo = layermgrRef.current.getLayer(key);
if (!layerInfo) {
continue;
}
layerInfo.refreshLayer(mapCtrl);
}
}, [tick, layerVisible]);
// 地图定位
useEffect(() => {
const mapCtrl = mapRef.current;
if (cameraTarget && mapCtrl) {
if (cameraTarget.center) {
mapCtrl.flyTo(cameraTarget)
} else if (cameraTarget.bounds) {
const { bounds, ...options } = cameraTarget;
mapCtrl.fitBounds(bounds, options);
}
}
}, [cameraTarget]);
useEffect(() => {
layermgrRef.current.init(layerSetting);
const map = new mapboxgl.Map({
container: mapContainerRef.current,
style: layermgrRef.current.getMapStyle(),
minZoom: 5,
maxZoom: 18,
pitch: config.homePitch,
bounds: config.initalExtent,
maxBounds: config.w_extent_mb,
preserveDrawingBuffer: true,
...initParams
});
map.on('load', () => {
mapRef.current = map;
forceRender();
window.__mapref = map;
//map.setTerrain({ 'source': 'mapbox-dem', 'exaggeration': 1.5 });
if (typeof onLoad === 'function') {
onLoad(map, mapContainerRef.current);
}
});
map.on('click', (e) => {
console.log(e);
const features = map.queryRenderedFeatures(e.point);
if (features.length) {
const feature = features[0];
const layer = layermgrRef.current.getLayerBySublater(feature.layer.id);
if (layer && layer.featureClicked) {
const props = { ...feature.properties };
for (const key in props) {
if (props[key] === 'null') {
props[key] = null;
}
if (props[key] === 'undefined') {
props[key] = undefined;
}
}
layer.featureClicked(props, dispatch);
}
}
});
map.on('mousemove', (e) => {
const features = map.queryRenderedFeatures(e.point);
if (features.length) {
const feature = features[0];
const layer = layermgrRef.current.getLayerBySublater(feature.layer.id);
let featureTip = null;
if (layer && layer.getFeatureTip) {
featureTip = layer.getFeatureTip(feature.properties);
}
dispatch.runtime.setFeatureTip({
tip: featureTip,
x: e.point.x,
y: e.point.y,
});
}
});
return () => {
map.remove();
mapRef.current = null;
window.__mapref = null;
forceRender();
}
// eslint-disable-next-line
}, []);
return (
<>
<div style={{ position: 'absolute', left: 0, right: 0, top: 0, bottom: 0 }} ref={mapContainerRef} />
<FeatureTip />
<FeaturePops mapCtrl={mapRef.current} />
<Markers mapCtrl={mapRef.current} />
</>
)
}