1. 在React-Create-APP中使用Cesium

2,390 阅读4分钟

一、简介

这个系列是想将自己做过的Cesium项目整理回顾,同时也希望能给看到的文章的朋友一点帮助。大部分内容规划都是简单的功能应用,后面可能会选我自己感兴趣的功能做分享。

本文主要介绍工程的技术选型,环境搭建和代码的简单实现。首先解释一下为什选择Craco。

我喜欢直接用 create-react-app 的搭建功能,不喜欢自定义太多,所以不想把工程 eject。所以craco 是不改工程默认设置下配置Webpack的很好的解决方法。

React 中使用实现目前我了解到的解决方案有两种:

1)resium, 我简单resium提供一套比较方便的接口组件,确实很容易上手,但是缺点可能是不如直接像SDK里面那种方式来的灵活;

2)craco-cesium 环境配置多个几个步骤,但总体上来说使用方法能接近于用在html中或者直接用webpack搭建工程那样直接使用cesium。我看工程本身也比较久了最先版是2019年的,如果将来create-react-app将来升级到webpack5等,可能这种方法存在风险。但显示用的话没问题。

因此,下面要讲的就是基于craco-cesium在create-react-app工程中使用cesium。

二、工程搭建

1. create-react-app

创建React工程,这里我使用了typescript的模版,主要是为了练习typescript使用。实际工作需要根据需求与资源情况来决定是使用JS还是TS。

yarn create react-app cesium-in-react --template typescript

工程建好后,调整一个目录结构,也可以按自己的习惯组织

image.png

2. craco与craco-cesium

安装 craco,craco-cesium。 craco-cesium 用起来很容易,直接参考文档就行。

yarn add @craco/craco craco-cesium cesium resium

安装好了之后需要处理两个地方:

  1. 修改 package.json 中的运行脚本
{
  // ...
  "scripts": {
    "start": "craco start", // react-scripts -> craco
    "build": "craco build", // react-scripts -> craco
    "test": "craco test",   // react-scripts -> craco
    "eject": "react-scripts eject"
  },
  // ...
}
  1. 配置Craco,在根目录下创建craco.config.js,然后配置craco-cesium
module.exports = {
  plugins: [
    {
      plugin: require("craco-cesium")()
    }
  ]
};

文档里面只有一个问题 Enabling HMR 应该是不用自己配置了。新版的的Create-React-APP 以及是支持了的。按章文档的会有问题

3. react-router

这个没什么好说的,安装引入之后把路由都配置好。

yarn add react-router-dom@6

image.png

4. less

我比较习惯使用Less所以需要在工程里面启用 Less,同样也是需要通过craco处理less样式文件的解析。这里用到到的是 craco-less

yarn add craco-less

然后在craco配置文件中使用配置

module.exports = {
  plugins: [
    {
      plugin: CracoCesiumPlugin(),
    },
    {
      plugin: CracoLessPlugin,
      options: {
        lessLoaderOptions: {
          lessOptions: {
            modifyVars: {
              "@primary-color": "#00b87e",
            },
            javascriptEnabled: true,
          },
        },
      },
    },
  ],
};

三、代码实现

1. 关键技术点

代码实现时主要是有两点需要注意

1)代码实现思路很简单,大致实现步骤为:页面初始化加载→监听到承载Viewer的DOM元素已加载完成→Viewer地图窗口初始化

  1. 承载Viewer的DOM元素样式要保证有一定的尺寸并且可见,简单点就是要元素本身要能看见,不然就算地图窗口初始化成功了也看不见

3)Viewer的实例需要用useRef来存,不然后面拿不到正在的地图窗口的实例,这点很重要。原因参考react useRef。参考

useRef  returns a mutable ref object whose .current  property is initialized to the passed argument (initialValue ). The returned object will persist for the full lifetime of the component.

2.代码实现

// src/routes/StartUp/index.tsx

import React, { useEffect, useRef } from "react";
import "./startUp.less";
import { Viewer } from "cesium";

const StartUp = () => {
  const csmViewerRef = useRef<null | Viewer>(null);
  const viewerContainerRef = useRef(null);

  useEffect(() => {
    if (viewerContainerRef.current && !csmViewerRef.current) {
      csmViewerRef.current = new Viewer("csm-viewer-container");
    }
  }, [viewerContainerRef]);

  return (
    <div
      className="csm-viewer-container"
      id="csm-viewer-container"
      ref={viewerContainerRef}
    ></div>
  );
};

export default StartUp;

image.png

四、总结

Cesium 在react中的使用起步是比较简单的,尤其是 craco-cesium 除了最麻烦的cesium引用的问题。初学者不一定一开始就用这个方案,因为这个方案要求你对Cesium和React都要有一定的熟悉程度,而且可能也在未知的问题。我也是试试看 ^ ^ 后面会继续分享常见GIS功能在 Cesium 中的实现,比如各类图层加载,地图上的 Popup Window,测量等。

参考与引用

  1. blog.isquaredsoftware.com/2017/03/dec…

源码请参看 我的GitHub ,由于文章是一边coding,一边写的所以 Github 里面的源码可能有点乱,可以根据功能来找对应的代码。后面会陆续整理完善。