1 Star 1 Fork 0

火星科技 / mars3d-react-project

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
Apache-2.0

基于React技术栈的 Mars3D🌎基础项目系统

Npm version Npm downloads GitHub stars star

## 项目介绍

Mars3D 基础项目 是基于Mars3D 平台做的一个应用系统,提供的一个基础项目模版,包含常用基础地图功能,可在该基础项目上快速开发搭建新项目。方便快速搭建三维地图产品,敏捷开发,可复用,支持各种配置,适合各种场景使用。

项目特性

  • 最新技术栈:使用 React/Vite 等前端前沿技术开发
  • TypeScript: 应用程序级 JavaScript 的语言
  • 适用于地图场景的 widget 模块化: 继续沿用了原生 JS 版本 widget 架构的一些思想,使用 react 方式实现了各 widget 功能

如果您不熟悉 React,也可以阅读:基础项目原生 JS 版基础项目 Vue 版

视频讲解

建议先看一遍视频讲解,再实际操作。您可以新页面查看高清视频

下载运行项目

下载代码

git clone https://github.com/marsgis/mars3d-react-project.git
  • Gitee:国内码云,下载速度快些。
git clone https://gitee.com/marsgis/mars3d-react-project.git

运行环境

  • 推荐使用 vscode,安装参考开发环境搭建教程
  • 安装 vscode 插件,推荐安装 ESlint 、 Prettier
  • 配置 vscode 参数
// setting.json相关配置
{
  "eslint.format.enable": true,
  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[html]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[react]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}

运行命令

请将机器 Node 版本升级到 v14 及以上版本

首次运行前安装依赖

npm install

//或使用代理
npm i --registry=http://registry.taobao.org

启动开发环境

npm run serve

编译构建

npm run build

运行效果

访问基础项目 React 版 在线体验效果和功能

image

浏览器支持

推荐使用Chrome 90+ 浏览器, 建议升级浏览器到最新版本访问。

IE Edge Firefox Chrome Safari
not support last 2 versions last 2 versions last 2 versions last 2 versions

如何反馈问题?

  • 发现您发现项目中存在的问题或者需要优化的地方;
  • 如果您有一些自己全新编写的示例,希望也开源与大家分享。

提交方式:

  • 欢迎在 github 或 gitee 上提交 PR
  • 如果对 git 不熟悉,也可以整理示例代码发送邮件到 wh@marsgis.cn 由我们来整理集成。

项目架构

技术选型

主要目录说明

mars3d-react-project
└───src                 主要项目代码
│   └───common          公共核心文件
│   └───components      公共组件
│   └───directive       指令
│   └───misc            ts模块定义
│   └───pages           页面入口
│   └───utils           工具方法
│   └───widget          功能相关的widget控件【重要】

└───public              静态资源
│   └───config          地图的配置文件等
│   └───img             图片资源

│─── .eslintrc.js        eslint配置文件
│─── package.json        项目配置信息
└─── vite.config.ts      vite 配置文件
└─── tsconfig.js         ts 配置文件
└─── *.html              各页面入口

功能主目录

项目所有功能主要在 src/widgets/*/*目录下,每一个功能对应了叶子目录下的一个index.tsxmap.ts 文件,复杂的 widget 目录下也会有相关子组件 xxx.tsx

react 下的 widget 设计,沿用了我们 原生 JS 版基础项目的设计理念:

  • 所有的 widget 都是按需加载
  • 只需要通过简单的配置,即可控制不同业务面板间的互斥关系
  • 提供 api 可以手动的控制面板的显示隐藏

widget 配置参数

widget 加载相关的代码在 src/common/store/widget.ts下,使用的 redux 管理相关状态,默认状态字段有

// 为 store state 声明类型
export interface DefaultOption {
  autoDisable?: boolean
  disableOther?: boolean | string[]
  group?: string // group相同的widget一定是互斥的
  meta?: any // 额外参数 不会在每次关闭后清除
}

export interface Widget {
  name: string // 唯一标识
  key?: string // 作为react diff 环节的key,用于控制组件重载
  component?: any // widget关联的异步组件
  autoDisable?: boolean // 是否能够被自动关闭
  disableOther?: boolean | string[] // 是否自动关闭其他widget,或通过数组指定需要被关闭的widget
  group?: string // group相同的widget一定是互斥的
  visible?: boolean // 显示隐藏
  data?: any // 额外传参 会在每次关闭后清除
  meta?: any // 额外参数 不会在每次关闭后清除
}

export interface WidgetState {
  widgets: Widget[] // widget具体配置
  openAtStart: string[] // 默认加载的widget
  defaultOption?: DefaultOption // 支持配置默认参数
}

widget 构流程图

示例的内部构造处理流程图:

image

如何增加新的 widget

下面我们以 src/widgets/demo/sample-dialog/ 为示例做讲解

1.创建示例

在 widgets 目录下按项目需要建立好多层目录,比如我们将测试和演示的 widget 放在src/widgets/demo目录下面,基础项目的功能放在src/widgets/basic目录下。

首先建立后 sample-dialog 目录,并参考已有示例新建index.tsxmap.ts 2 个文件。

index.tsx

index.tsx 中用来编写 react 组件的代码,这个文件必须通过 export default 的方式导出一个 react 组件,这个组件可以使 class 组件,也可以是函数组件

// 函数组件
import * as mapWork from "./map"
import { useLifecycle } from "@mars/common/uses/useLifecycle"
import { MarsDialog } from "@mars/components/MarsUI"
import { Space } from "antd"
import { useRef } from "react"

export default function (props) {
  useLifecycle(mapWork)

  const guiRef = useRef<any>()

  return (
    <MarsDialog title="函数组件" right={10} top={50} width={300} {...props}>
      我是函数组件
    </MarsDialog>
  )
}
// class组件
import { withLifeCyle } from "@mars/common/uses/useLifecycle"
import { MarsDialog } from "@mars/components/MarsUI"
import { Component } from "react"
import * as mapWork from "./main"

class Test extends Component<any, any> {
  constructor(props) {
    super(props)
    this.state = {
      test: ""
    }
  }

  render() {
    return (
      <MarsDialog title="class组件" right={10} top={50} width={300} {...props}>
        我是class组件
      </MarsDialog>
    )
  }
}

export default withLifeCyle(Test, mapWork)
配置 widget 的 props 参数

widget 的 prop 参数默认有四中配置方式,默认情况下优先级从低到高分别为 内联 prop、defaultOption 中的 props、meta 中的 props 配置,动态传参,使用方式如下

// 内联
<MarsDialog title="图上量算" width="300" height="530" top="50"></MarsDialog>
// defaultOption中 注意 必须是meta
const store: StoreOptions<State> = {
  state: {
    defaultOption: {
      meta: {
        props: {
          top: 110
        }
      }
    },
    widgets: []
  }
}
// meta中
widgets = [
  {
    component: lazy(() => import("@mars/widgets/hello.tsx")),
    name: "hello",
    autoDisable: true,
    meta: {
      props: {
        top: 70
      }
    }
  }
]
// 动态传参
activate({
  name: "hello",
  data: {
    props: {
      top: 70
    }
  }
})
map.ts

react 中需要调用地图方法时,需得启用 map.ts 的生命周期,并且在 map.ts 生命周期中获取 map 对象。 但是函数组件和 class 组件的处理方式有所不同

  • 函数组件: 在函数体中调用 useLifecycle(mapWork) 来启用 map.ts 的生命周期
  • class 组件:导出组件时 调用 withLifeCyle(组件, mapWork) 来启用 map.ts 的生命周期

注意:

  1. 开启生命周期的操作只需要在 index.tsx 中执行,子组件不需要。

map.ts

map.ts 完整代码为:

import * as mars3d from "mars3d"

export let map: mars3d.Map // 地图对象

// 事件对象,用于抛出事件给react
export const eventTarget = new mars3d.BaseClass()

// 初始化当前业务
export function onMounted(mapInstance: mars3d.Map): void {
  map = mapInstance // 记录map
}

// 释放当前业务
export function onUnmounted(): void {
  map = null
}

// 绘制矩形(演示map.js与index.react的交互)
export function drawExtent(): void {
  map.graphicLayer.clear()
  // 绘制矩形
  map.graphicLayer.startDraw({
    type: "rectangle",
    style: {
      fill: true,
      color: "rgba(255,255,0,0.2)",
      outline: true,
      outlineWidth: 2,
      outlineColor: "rgba(255,255,0,1)"
    },
    success: function (graphic: mars3d.graphic.RectangleEntity) {
      const rectangle = graphic.getRectangle({ isFormat: true })
      eventTarget.fire("drawExtent", { extent: JSON.stringify(rectangle) }) // 抛出事件,可以react中去监听事件
    }
  })
}

其中:

onMounted

初始化当前地图业务的钩子方法,可以通过 onMounted 函数的获取到 map 主对象。

export function onMounted(mapInstance: mars3d.Map): void {
  map = mapInstance // 记录map 初始化当前业务
}

如果未调用,请请参考之前的步骤,检查是否正确的启用生命周期

onUnmounted

释放当前地图业务的钩子方法, 一般在 onMounted 添加的图层、绑定的事件,在 onUnmounted 中都需要做相反的移除、解绑等操作。

export function onUnmounted(): void {
  map = null // 释放当前业务
}

map.tsindex.tsx各自代码业务分离的原则

  • 涉及地图业务的操作均写在 map.ts 中
  • 涉及 UI 层面、和地图无关的操作均写在 index.tsx 中,react 中尽量不使用 mars3d 和 Cesium 开头的类

index.tsx 与 map.ts 交互

  1. index.tsx 直接调用 map.ts 中 导出的函数或对象
  2. index.tsx 调用 map.ts 中的函数拿到返回值,继续后续处理,异步操作返回值可以是 Promise
  3. map.ts 主动触发 ui 变化,通过 mars3d.BaseClass 事件中心处理。如
// map.ts
export const eventTarget = new mars3d.BaseClass()

function change() {
  mapWork.eventTarget.fire("change", { value: "hello change" })
}

// index.tsx
// 监听事件
mapWork.eventTarget.on("change", change)

// 组件卸载时
mapWork.eventTarget.off("change", change) // 注意:请及时销毁事件绑定

2.相关页面加入菜单入口

store.ts 清单配置

在对应 page 页面下的 src/pages/demo/widget-store.ts 中,需要配置刚才新建的 widget 相关信息;

import type { WidgetState } from "@mars/common/store/widget"
import { lazy } from "react"

const store: StoreOptions<WidgetState> = {
  state: {
    //已忽略其他配置
    widgets: [
      {
        component: lazy(() => import("@mars/widgets/demo/sample-dialog/index.tsx")),
        name: "sample-dialog"
      }
    ]
  }
}
export default store

其中 state 下的配置参数参考 widget 配置参数

更多参数建议阅读源码的 src/common/store/widget.ts (教程可能滞后,请参考源码注释为准)

菜单或其他入口文件中

在需要的菜单单击事件或其他对象触发代码中,加入activate('sample-dialog')来激活我们刚加入的控件,

下面已目录为例:

widgets/demo/menu/index.tsx中加入“弹窗示例”按钮,按钮单击事件调用对应方法,

activate 和 disable 函数支持 string(直接传递 name) 和 Widget(传递 widget 对象,将会合并传递的属性,必须包含 name 字段) 类型的参数,上述 name 字段与 store.ts 中的 name 需要一致。

将当前项目集成到自己的项目中(合并 2 个项目)

前提条件:需要 2 个项目的技术栈基本是一致的,比如react + ts+ant-design

流程概览:

此处演示的是vite技术栈下的操作

需要拷贝的目录和文件:

  • /src/ 拷贝到一个文件夹如 /src/marsgis
  • /public/ 拷贝到 /public/
  • /src/pages/index/widget-store.ts 拷贝到/src/marsgis/widget-store.ts

需要修改自己项目的文件:

  • package.json
  • vite.config.ts
  • src/main.js

1. 拷贝基础项目 src 代码

在原有项目中新建目录src/marsgis,将基础项目 src 代码拷贝到src/marsgis目录下面,其中 pages 目录非必须,可以按需拷贝。

2. 拷贝 public 下的资源

将基础项目public下所有文件拷贝到自己项目的public目录下。

3. package.json 依赖的融合

复制 package.json 依赖包,保证依赖存在且版本正确。

4. 修改项目别名等配置

修改vite.config.ts 配置文件中的项目别名配置和 process 相关配置

alias: {
  {
    find: /@mars\//,
    replacement: pathResolve('src/marsgis') + '/',
  }
}

define: {
  'process.env': {
    BASE_URL: '/',
  },
}

5. 修改初始化相关依赖

src/pages/index/widget-store.ts配置文件拷贝src/marsgis/widget-store.ts位置。

再在src/main.js文件中加载和初始化相关依赖。

import "mars3d-cesium/Build/Cesium/Widgets/widgets.css"
import "mars3d/dist/mars3d.css"
import "@mars/assets/style/index.less"

import { createRoot } from "react-dom/client"
import MainView from "@mars/components/MarsWork/MainView"
import { generateWidgetView } from "@mars/common/store/widget"
import widgetState from "./widget-state"


const WidgetView = generateWidgetView(widgetState)

const reactApp = createRoot(document.getElementById("root"))

reactApp.render(
  <MainView>
    <WidgetView></WidgetView>
  </MainView>
)

6.复制对应 react 页面代码

复制对应页面代码到组件中, 例如拷贝 src/pages/index/App.tsx 代码到自己项目需要展示地图的 react 文件中。

7. 合并项目规范等配置信息(可选)

如果没有下面文件,可以直接拷贝到自己项目中, 如果已有对应文件,可以对比参数,按需拷贝相关配置进已有文件中。

  • 复制/.editorconfig 文件到src/marsgis/目录下
  • 复制/.eslintrc.js 文件到src/marsgis/目录下
  • 复制/.prettierrc 文件到src/marsgis/目录下
  • 修改/tsconfig.json 文件

如果项目中采用的 eslint 标准库与基础项目不一致,则根据提示安装对应的依赖,相关依赖如下, 按照项目实际情况安装,并作相应调整.

8. 处理样式冲突

基础项目已经基本保证不会影响外部样式,此处要处理的是您项目中的全局样式对 mars3d 相关组件的影响。修改相关 CSS 保证基础项目功能 UI 正常即可。

开发中常见问题

1. 如何切换 mars3d 到授权版

参考 获取 Mars3D SDK类库中“从 Mars3D官网 下载获取”章节介绍。

流程大概是:

  • 配置后,无需改动源码,在项目代码中使用时与使用 npm 包是一样的方式,如 import * as mars3d from "mars3d";
  • 将 npm 安装后的node_modules/mars3d/下的所有文件拷贝一份放在packages/mars3d/目录。
  • mars3d-sdk.rar离线包内文件 覆盖至packages/mars3d/dist/目录下。
  • 修改package.json中 mars3d 包配置为: "mars3d": "file:packages/mars3d",

image

2. 局域网离线使用时注意事项

平台所有代码层面来说支持离线运行和使用的,但需要注意的是离线时的地图服务的相关处理。

如果局域网内有相关地形、卫星底图服务可以按内网服务类型和 URL 地址替换下config.json构造Map的代码中的默认地形和底图。

如果局域网内没有相关服务,可以按下面处理:

  • 修改 config.json 中terrain配置中,将已有的"show": true配置,改为"show": false
  • 修改 config.json 中basemaps数组配置中,将已有的"show": true的图层,将该值改为"show": false ,并将单张图片或离线地图加上"show": true,并修改相关 URL 地址。
  • 您也可以参考教程发布三维数据服务进行部署离线地图服务,里面也有一些示例离线数据。

Mars3D 是什么

Mars3D平台火星科技研发的一款基于 WebGL 技术实现的三维客户端开发平台,基于Cesium优化提升与 B/S 架构设计,支持多行业扩展的轻量级高效能 GIS 开发平台,能够免安装、无插件地在浏览器中高效运行,并可快速接入与使用多种 GIS 数据和三维模型,呈现三维空间的可视化,完成平台在不同行业的灵活应用。

Mars3D 平台可用于构建无插件、跨操作系统、 跨浏览器的三维 GIS 应用程序。平台使用 WebGL 来进行硬件加速图形化,跨平台、跨浏览器来实现真正的动态大数据三维可视化。通过 Mars3D 产品可快速实现浏览器和移动端上美观、流畅的三维地图呈现与空间分析。

相关网站

版权说明

  1. Mars3D 平台由火星科技自主研发,拥有所有权利。
  2. 任何个人或组织可以在遵守相关要求下可以免费无限制使用。
Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ http://mars3d.cn/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [2017-2024] [Hefei Mars Technology Co., LTD., China] http://mars3d.cn/ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

简介

基础项目 React版 展开 收起
TypeScript 等 4 种语言
Apache-2.0
取消

发行版 (4)

全部

贡献者

全部

近期动态

加载更多
不能加载更多了
1
https://gitee.com/marsgis/mars3d-react-project.git
git@gitee.com:marsgis/mars3d-react-project.git
marsgis
mars3d-react-project
mars3d-react-project
master

搜索帮助