一、环境描述
React集成Cesium地图需要注意软件兼容性问题,可以从官网或者百度文章查询React和Cesium地图的版本兼容性,
1、软件版本
(1)create-react-app创建项目;
(2)React版本:18.3.1;
(3)Cesium版本:1.62.0;
(4)copy-webpack-plugin:5.1.2;
(5)Node版本:14.21.3
二、创建React项目
1、创建项目
npx create-react-app react-test
2、启动项目
cd react-test
npm run start
3、安装Cesium
npm i cesium@1.62.0 --save
4、安装copy-webpack-plugin
npm i copy-webpack-plugin@5 -D
5、运行npm run eject
Cesium静态资源需要webpack配置,执行npm run eject可以生成webpack配置,运行前先查看当前git版本是否有提交,如果未提交,需要先本地提交git,否则npm run eject会执行失败。
(1)提交git(如果版本已经提交,无需执行)
git add .
git commit -m "React Init"
(2)执行npm run eject
npm run eject// 执行成功后,生成的文件列表
// config/
// jest/
// webpack/
// env.js
// getHttpsConfig.js
// modules.js
// paths.js
// webpack.config.js
// webpackDevServer.config.js// scripts/
// build.js
// start.js
// test.js
三、webpack配置
1、修改webpack.config.js文件
// 1、引入copy-webpack-plugin
const CopyWebpackPlugin = require('copy-webpack-plugin');// 2、引入Cesium静态资源
const cesiumSource = "node_modules/cesium/Source";
const cesiumWorkers = '../Build/Cesium/Workers';
const fileFolder = "src";// 3、在return下的output对象中添加配置
sourcePrefix: '',// 4、在return下的output对象后添加配置(与output对象同级)
amd: {toUrlUndefined: true
},// 5、在return下的resolve对象下的alias对象中添加配置
cesium: path.resolve(cesiumSource),// 6、在return下的module对象中添加配置
unknownContextCritical: false,// 7、在return下的plugins数组中添加配置
new CopyWebpackPlugin([{from: path.join(cesiumSource, cesiumWorkers),to: "Workers"
}]),
new CopyWebpackPlugin([{from: path.join(cesiumSource, 'Assets'),to: 'Assets'
}]),
new CopyWebpackPlugin([{from: path.join(cesiumSource, 'Widgets'),to: 'Widgets'
}]),new CopyWebpackPlugin([{ from: path.join(fileFolder, 'static'), to: 'Static' }
]),
new webpack.DefinePlugin({CESIUM_BASE_URL: JSON.stringify('')
}),
四、项目配置
1、路由配置
(1)路由文件配置
在src/创建一个名为router.js的文件(文件名称和位置可以自己规划)
// 引入组件
import App from "./App";
import CesiumMapFunction from './components/CesiumMapFunction';
import CesiumMapClass from './components/CesiumMapClass';import { createBrowserRouter } from "react-router-dom";const router = createBrowserRouter([{path: "/",element: <App />,children: [{path: "",element: <CesiumMapFunction />},{path: "/cesiumFunction",element: <CesiumMapFunction />},{path: "/cesiumClass",element: <CesiumMapClass />}]},
])export default router
(2)index.js文件配置
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { RouterProvider } from 'react-router-dom';
import router from './router';const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(// <React.StrictMode> // 注意注释React严格模式<RouterProvider router={router}><App /></RouterProvider>// </React.StrictMode>
);reportWebVitals();
(3)App.js文件配置
import './App.css';
import Header from './components/Header';
import { Outlet, useNavigate } from 'react-router-dom';
import { useState } from 'react';function App() {const [isActive, setIsActive] = useState(1)const navigate = useNavigate()function clickMenu(path, menuId) {if (isActive === menuId) {return}// 保存当前点击的菜单IDsetIsActive(menuId)// 跳转路由navigate(path)}return (<div className="App"><Header clickMenu={clickMenu} active={isActive}></Header><div className="content"><Outlet /></div></div>);
}export default App;
2、地图组件配置
(1)Header.js配置
// css文件
import "./css/Header.css"// 数据来源
const menuData = [{id: 1,label: "函数组件Cesium",path: "/cesiumFunction"},{id: 2,label: "类组件Cesium",path: "/cesiumClass"}
]// 数据过滤
function FilterData({ clickList, isActive }) {return menuData.map(row => {return (<li className={isActive === row.id ? 'isActive' : ''} onClick={() => { clickList(row.path, row.id) }} key={row.id} >{row.label}</li >)})
}// 渲染页面
export default function Header({ clickMenu, active }) {return (<ul className="menuList"><FilterData clickList={clickMenu} isActive={active} /></ul>)
}
(2)函数组件(CesiumMapFunction.js)
import Cesium from 'cesium/Cesium'
import 'cesium/Widgets/widgets.css'
import { useEffect } from "react";
import "./css/CesiumMap.css"export default function CesiumMapFunction() {useEffect(() => {Cesium.Ion.defaultAccessToken = "your_map_token";// 初始化Cesiumconst viewer = new Cesium.Viewer('cesiumContainer', {geocoder: false, //右上角搜索homeButton: false, //右上角homesceneModePicker: false, //右上角2D/3D切换baseLayerPicker: false, //右上角地形navigationHelpButton: false, //右上角帮助animation: false, //左下角圆盘动画控件timeline: true, //底部时间轴fullscreenButton: false, //右下角全屏控件vrButton: false, //如果设置为true,将创建VRButton小部件。scene3DOnly: false, // 每个几何实例仅以3D渲染以节省GPU内存infoBox: false, //隐藏点击要素后的提示信息imageryProvider: new Cesium.ArcGisMapServerImageryProvider({url: "your_map_url",}), //地图地址})// 隐藏左下角商标信息viewer._cesiumWidget._creditContainer.style.display = "none";// 隐藏底部时间轴viewer.timeline.container.style.display = "none";//开启深度检测viewer.scene.globe.depthTestAgainstTerrain = false;// 启用光照viewer.scene.globe.enableLighting = true;// 设置相机初始位置viewer.camera.setView({destination: Cesium.Cartesian3.fromDegrees(110,30,10000),// 设置相机方向,俯视和仰视的视角orientation: {heading: Cesium.Math.toRadians(0), //坐标系旋转0度pitch: Cesium.Math.toRadians(-90), //设置俯仰角度为-90度},});return () => {console.log("组件销毁前执行")}}, [])return (<div className='cesiumMap'><div id="cesiumContainer" /></div>);
}
(3)类组件(CesiumMapClass.js)
import React, { Component } from 'react'
import Cesium from 'cesium/Cesium'
import 'cesium/Widgets/widgets.css'
import './css/CesiumMap.css'Cesium.Ion.defaultAccessToken = "your_map_token"export default class App extends Component {componentDidMount() {const viewer = new Cesium.Viewer("cesiumContainer", {geocoder: false, //右上角搜索homeButton: false, //右上角homesceneModePicker: false, //右上角2D/3D切换baseLayerPicker: false, //右上角地形navigationHelpButton: false, //右上角帮助animation: false, //左下角圆盘动画控件timeline: true, //底部时间轴fullscreenButton: false, //右下角全屏控件vrButton: false, //如果设置为true,将创建VRButton小部件。scene3DOnly: false, // 每个几何实例仅以3D渲染以节省GPU内存infoBox: false, //隐藏点击要素后的提示信息imageryProvider: new Cesium.ArcGisMapServerImageryProvider({url: "your_map_url",}), //地图地址})// 隐藏左下角商标信息viewer._cesiumWidget._creditContainer.style.display = "none";// 隐藏底部时间轴viewer.timeline.container.style.display = "none";//开启深度检测viewer.scene.globe.depthTestAgainstTerrain = false;// 启用光照viewer.scene.globe.enableLighting = true;// 设置相机初始位置viewer.camera.setView({destination: Cesium.Cartesian3.fromDegrees(110,30,10000),// 设置相机方向,俯视和仰视的视角orientation: {heading: Cesium.Math.toRadians(0), //坐标系旋转0度pitch: Cesium.Math.toRadians(-90), //设置俯仰角度为-90度},});}render() {return (<div className='cesiumMap'><div id="cesiumContainer"></div></div>)}
}