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);
|
|
|
|
|
|
}
|
2025-06-06 16:32:34 +08:00
|
|
|
|
if(feature.layer.id==='sk1111'||feature.layer.id==='sk2222'){
|
|
|
|
|
|
const record = feature.properties
|
|
|
|
|
|
dispatch.runtime.setFeaturePop({ type: 'RealSkPop', properties: record, coordinates: [record.lgtd, record.lttd] });
|
2025-06-09 15:49:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
if(feature.layer.id==='关联站点'){
|
|
|
|
|
|
const record = feature.properties
|
|
|
|
|
|
// dispatch.runtime.setFeaturePop({ type: 'RealSkPop', properties: record, coordinates: [record.lgtd, record.lttd] });
|
2025-06-06 16:32:34 +08:00
|
|
|
|
}
|
2025-05-19 14:26:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
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} />
|
|
|
|
|
|
</>
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|