2026-02-06 11:00:16 +08:00
|
|
|
import React, { useEffect, useReducer, useRef, useState } from 'react';
|
|
|
|
|
import { useDispatch, useSelector } from 'react-redux';
|
|
|
|
|
import { Checkbox, message } from 'antd';
|
2026-02-07 15:27:30 +08:00
|
|
|
import { CloseOutlined } from '@ant-design/icons';
|
2026-02-06 11:00:16 +08:00
|
|
|
import { useLocation } from 'react-router'
|
|
|
|
|
import './index.less'
|
2026-02-08 09:49:07 +08:00
|
|
|
import { config } from '@/config';
|
2026-02-26 09:13:17 +08:00
|
|
|
import LayerBox from './layer'
|
|
|
|
|
import GlobalSearch from './globalSearch'
|
2026-02-06 11:00:16 +08:00
|
|
|
|
|
|
|
|
export default function Btn() {
|
2026-02-07 15:27:30 +08:00
|
|
|
const dispatch = useDispatch()
|
|
|
|
|
const location = useLocation()
|
2026-02-06 11:00:16 +08:00
|
|
|
const showPanels = useSelector((s) => s.runtime.showPanels)
|
|
|
|
|
const layerVisible = useSelector(s => s.map.layerVisible);
|
2026-02-08 09:49:07 +08:00
|
|
|
const map = useSelector(s => s.map.map);
|
2026-02-07 15:27:30 +08:00
|
|
|
const isFullScreen = useSelector(s => s.runtime.isFullScreen)
|
|
|
|
|
const mapCenter = useSelector(s => s.runtime.mapCenter)||{}
|
2026-02-06 11:00:16 +08:00
|
|
|
const mode = useSelector(s=>s.map.mode)
|
2026-02-07 15:27:30 +08:00
|
|
|
const [open, setOpen] = useState(false)//是否弹出图层窗口
|
2026-02-26 09:13:17 +08:00
|
|
|
const [searchOpen, SearchOpen] = useState(false)//弹出全局搜索
|
2026-02-07 15:27:30 +08:00
|
|
|
const [targetZoom, setTargetZoom] = useState(null)//点击缩放按钮后地图目标的zoom值
|
2026-02-26 09:13:17 +08:00
|
|
|
const lastCameraTargetTimeRef = useRef(0);//节流
|
2026-02-07 15:27:30 +08:00
|
|
|
|
|
|
|
|
useEffect(()=>{
|
|
|
|
|
//移动地图后同步targetZoom值
|
|
|
|
|
setTargetZoom(mapCenter?.zoom||null)
|
|
|
|
|
},[mapCenter])
|
2026-02-06 11:00:16 +08:00
|
|
|
|
2026-02-26 09:13:17 +08:00
|
|
|
//切换图层
|
2026-02-06 11:00:16 +08:00
|
|
|
const layerVisibleChanged = (event)=>{
|
|
|
|
|
const vo = { [event.target.name]: event.target.checked };
|
2026-02-26 09:13:17 +08:00
|
|
|
const now = Date.now()
|
|
|
|
|
if(
|
|
|
|
|
event.target.checked &&
|
|
|
|
|
(event.target.name==='SYLayer' || event.target.name==='SLLayer' || event.target.name==='WYLayer') &&
|
|
|
|
|
(now-lastCameraTargetTimeRef.current >=1000)
|
|
|
|
|
){
|
|
|
|
|
dispatch.runtime.setCameraTarget({
|
|
|
|
|
center: [114.15437134051429, 29.744689445729758],
|
|
|
|
|
zoom: 18,
|
|
|
|
|
pitch: 60
|
|
|
|
|
})
|
|
|
|
|
lastCameraTargetTimeRef.current = now;
|
2026-02-08 09:49:07 +08:00
|
|
|
}
|
2026-02-06 11:00:16 +08:00
|
|
|
dispatch.map.setLayerVisible(vo);
|
|
|
|
|
}
|
2026-02-26 09:13:17 +08:00
|
|
|
|
|
|
|
|
//切换地图框架
|
2026-02-08 09:49:07 +08:00
|
|
|
const mapType = (name)=>{
|
|
|
|
|
if(name==='2d'){
|
2026-02-06 11:00:16 +08:00
|
|
|
dispatch.map.setMode('2d');
|
|
|
|
|
dispatch.map.setLayerVisible({ ['SatelliteImage']: true });
|
|
|
|
|
}
|
2026-02-08 09:49:07 +08:00
|
|
|
if(name === '3d'){
|
2026-02-06 11:00:16 +08:00
|
|
|
if(location.pathname==='/mgr/sy/tqyb'){
|
|
|
|
|
message.error('天气预报无法切换3d视图')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
dispatch.map.setLayerVisible({ ['SatelliteImage']: false });
|
2026-02-08 09:49:07 +08:00
|
|
|
dispatch.map.setMode('3d');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ExportImage = async () => {
|
|
|
|
|
message.warn('功能开发中')
|
|
|
|
|
return
|
|
|
|
|
if(map._cesiumWidget){
|
|
|
|
|
map.render();
|
|
|
|
|
|
|
|
|
|
// 获取Canvas
|
|
|
|
|
const canvas = map.scene.canvas;
|
|
|
|
|
|
|
|
|
|
// 创建下载链接
|
|
|
|
|
const downloadLink = document.createElement('a');
|
|
|
|
|
downloadLink.href = canvas.toDataURL('image/png');
|
|
|
|
|
downloadLink.download = 'cesium-screenshot.png';
|
|
|
|
|
downloadLink.style.display = 'none';
|
|
|
|
|
|
|
|
|
|
// 触发下载
|
|
|
|
|
document.body.appendChild(downloadLink);
|
|
|
|
|
downloadLink.click();
|
|
|
|
|
document.body.removeChild(downloadLink);
|
|
|
|
|
}else{
|
|
|
|
|
map.once('rendercomplete', function() {
|
|
|
|
|
const canvas = map.getViewport().querySelector('.ol-layer canvas');
|
|
|
|
|
const link = document.createElement('a');
|
|
|
|
|
link.download = 'map.png';
|
|
|
|
|
link.href = canvas.toDataURL('image/png');
|
|
|
|
|
link.click();
|
|
|
|
|
});
|
|
|
|
|
map.renderSync(); // 触发重新渲染以确保画面完整
|
2026-02-06 11:00:16 +08:00
|
|
|
}
|
2026-02-08 09:49:07 +08:00
|
|
|
|
2026-02-06 11:00:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
2026-02-08 16:54:54 +08:00
|
|
|
<div className="mapToolBox" style={{right: showPanels?'23.5%':'10px'}}>
|
2026-02-06 11:00:16 +08:00
|
|
|
<div className='mapToolBtn'>
|
2026-02-07 15:27:30 +08:00
|
|
|
<div title={`${showPanels?'收起':'展开'}功能块`} onClick={()=>dispatch.runtime.setShowPanels(!showPanels)}>
|
|
|
|
|
<img className='mapToolBtnIcon' src={`${process.env.PUBLIC_URL}/assets/icons/${showPanels?'shouqi.png':'zhankai.png'}`} />
|
|
|
|
|
</div>
|
2026-02-26 09:13:17 +08:00
|
|
|
<div title="查询" onClick={()=>{
|
|
|
|
|
if(!searchOpen){setOpen(false)}
|
|
|
|
|
SearchOpen(!searchOpen)
|
|
|
|
|
}}>
|
2026-02-07 15:27:30 +08:00
|
|
|
<img className='mapToolBtnIcon' src={`${process.env.PUBLIC_URL}/assets/icons/search.png`} />
|
2026-02-06 11:00:16 +08:00
|
|
|
</div>
|
|
|
|
|
<div title="还原地图展示位置" onClick={()=>dispatch.runtime.setHome()}>
|
2026-02-07 15:27:30 +08:00
|
|
|
<img className='mapToolBtnIcon' style={{padding:'5px'}} src={`${process.env.PUBLIC_URL}/assets/icons/center.png`} />
|
2026-02-06 11:00:16 +08:00
|
|
|
</div>
|
2026-02-08 09:49:07 +08:00
|
|
|
<div title="天气" onClick={()=>{message.warn('功能开发中')}}>
|
2026-02-07 15:27:30 +08:00
|
|
|
<img className='mapToolBtnIcon' style={{padding:'5px'}} src={`${process.env.PUBLIC_URL}/assets/icons/tianqi.png`} />
|
|
|
|
|
</div>
|
|
|
|
|
<div title="放大" onClick={()=>{
|
|
|
|
|
if(mapCenter?.zoom === targetZoom){
|
|
|
|
|
dispatch.runtime.setCameraTarget({...mapCenter, zoom: mapCenter.zoom + 1, fixed:true})
|
|
|
|
|
setTargetZoom(mapCenter.zoom + 1)
|
|
|
|
|
}
|
|
|
|
|
}}>
|
|
|
|
|
<img className='mapToolBtnIcon' style={{padding:'5px'}} src={`${process.env.PUBLIC_URL}/assets/icons/fangda.png`} />
|
|
|
|
|
</div>
|
|
|
|
|
<div title="缩小" onClick={()=>{
|
|
|
|
|
if(mapCenter?.zoom === targetZoom){
|
|
|
|
|
dispatch.runtime.setCameraTarget({...mapCenter, zoom: mapCenter.zoom - 1, fixed:true })
|
|
|
|
|
setTargetZoom(mapCenter.zoom - 1)
|
2026-02-06 11:00:16 +08:00
|
|
|
}
|
2026-02-07 15:27:30 +08:00
|
|
|
}}>
|
|
|
|
|
<img className='mapToolBtnIcon' style={{padding:'5px'}} src={`${process.env.PUBLIC_URL}/assets/icons/suoxiao.png`} />
|
|
|
|
|
</div>
|
2026-02-08 09:49:07 +08:00
|
|
|
<div title="截图" onClick={()=>ExportImage()}>
|
2026-02-07 15:27:30 +08:00
|
|
|
<img className='mapToolBtnIcon' style={{padding:'5px'}} src={`${process.env.PUBLIC_URL}/assets/icons/download.png`} />
|
|
|
|
|
</div>
|
|
|
|
|
<div title={isFullScreen?"退出全屏":"进入全屏"} onClick={()=>dispatch.runtime.setIsFullScreen(!isFullScreen)}>
|
|
|
|
|
<img className='mapToolBtnIcon' src={`${process.env.PUBLIC_URL}/assets/icons/${isFullScreen?'quanping2.png':'quanping.png'}`} />
|
|
|
|
|
</div>
|
2026-02-26 09:13:17 +08:00
|
|
|
<div title="地图展示图层控制" onClick={()=>{
|
|
|
|
|
if(!open){SearchOpen(false)}
|
|
|
|
|
setOpen(!open)}
|
|
|
|
|
}>
|
2026-02-07 15:27:30 +08:00
|
|
|
<img className='mapToolBtnIcon' src={`${process.env.PUBLIC_URL}/assets/icons/tuceng.png`} />
|
2026-02-06 11:00:16 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
2026-02-26 09:13:17 +08:00
|
|
|
<LayerBox
|
|
|
|
|
open={open}
|
|
|
|
|
mode={mode}
|
|
|
|
|
layerVisible={layerVisible}
|
|
|
|
|
setOpen={setOpen}
|
|
|
|
|
mapType={mapType}
|
|
|
|
|
layerVisibleChanged={layerVisibleChanged}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<GlobalSearch
|
|
|
|
|
open={searchOpen}
|
|
|
|
|
mode={mode}
|
|
|
|
|
layerVisible={layerVisible}
|
|
|
|
|
setOpen={SearchOpen}
|
|
|
|
|
mapType={mapType}
|
|
|
|
|
layerVisibleChanged={layerVisibleChanged}
|
|
|
|
|
/>
|
2026-02-06 11:00:16 +08:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|