React项目-Cesium地图初始化

一、环境描述

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、创建项目
javascript 复制代码
npx create-react-app react-test
2、启动项目
javascript 复制代码
cd react-test
npm run start
3、安装Cesium
javascript 复制代码
npm i cesium@1.62.0 --save
4、安装copy-webpack-plugin
javascript 复制代码
npm i copy-webpack-plugin@5 -D
5、运行npm run eject

Cesium静态资源需要webpack配置,执行npm run eject可以生成webpack配置,运行前先查看当前git版本是否有提交,如果未提交,需要先本地提交git,否则npm run eject会执行失败。

(1)提交git(如果版本已经提交,无需执行)

javascript 复制代码
git add .
git commit -m "React Init"

(2)执行npm run eject

javascript 复制代码
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文件
javascript 复制代码
// 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的文件(文件名称和位置可以自己规划)

javascript 复制代码
// 引入组件
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文件配置

javascript 复制代码
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文件配置

javascript 复制代码
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
    }
    // 保存当前点击的菜单ID
    setIsActive(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配置

javascript 复制代码
// 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)

javascript 复制代码
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";

    // 初始化Cesium
    const viewer = new Cesium.Viewer('cesiumContainer', {
      geocoder: false, //右上角搜索
      homeButton: false, //右上角home
      sceneModePicker: 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)

javascript 复制代码
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, //右上角home
      sceneModePicker: 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>
    )
  }
}
相关推荐
奔跑草-1 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
林太白8 小时前
❤React-React 组件通讯
前端·javascript·react.js
豆华8 小时前
React 中 为什么多个 JSX 标签需要被一个父元素包裹?
前端·react.js·前端框架
前端熊猫8 小时前
React第一个项目
前端·javascript·react.js
练习两年半的工程师8 小时前
使用React和Vite构建一个AirBnb Experiences克隆网站
前端·react.js·前端框架
林太白8 小时前
❤React-JSX语法认识和使用
前端·react.js·前端框架
女生也可以敲代码9 小时前
react中如何在一张图片上加一个灰色蒙层,并添加事件?
前端·react.js·前端框架
布兰妮甜9 小时前
前端框架大比拼:React.js, Vue.js 及 Angular 的优势与适用场景探讨
前端·vue.js·react.js·前端框架·angular.js
老码沉思录10 小时前
React Native 全栈开发实战班 - 核心组件与导航
javascript·react native·react.js