对mars3d框架研究中的感悟

感悟:之前学习cesium三维框架时没有具体的项目经验,总是感觉数据和组件的逻辑很乱,没有一个确定的规范,每次把项目框架化或者说各部分功能分离化,但最终还是会写到一起去。
但在mars3d中,我通过对框架的学习了解他们是如何将框架分离化的,大体上可以分为3部分:1、工具栏。2、cesium.viewer。3、用于将工具栏信息传递给cesium.viewer的js代码。
其中cesium.viewer唯一化,然后一个js代码和index.vue工具栏绑定组合成一个组件,其中可以有多个组件。

技术选型

主要目录说明

mars3d-vue-example
└───src                 主要项目代码
│   └───components      vue组件代码【重要】
│   └───example         示例代码【重要】
│   └───misc            主要存放ts相关的模块定义
│   └───pages           页面入口
│   └───styles          样式文件
│   └───utils           工具方法
└───public              无需编译构建的静态资源【重要】
│   └───config          项目和功能的配置文件
│   └───img             图片资源
│   └───lib             示例依赖资源
│   └───temp            示例的公共基础代码
│───.eslintrc.js        eslint配置文件
│─── package.json       项目配置信息
└─── vite.config.ts     vite 配置文件
└─── index.html         列表页入口
└─── editor-vue.html        编辑器页面入口

与示例相关的3个主要目录是:src\examplepublicsrc\components(部分功能依赖)。

示例主目录

  • 位置 src/example
  • 项目中的每一个示例对应了本目录下的一个 map.js 文件,如果包含 ui 面板,需要创建一个 index.vue
  • 一些情况下可以将 example 视为 public 下的一个目录

依赖资源

配置的依赖会在html中按配置顺序加载,注意配置时依赖之间的先后顺序。

  1. libs 依赖,公共的通用依赖,统一放在public/lib/目录下,并由includeLibs.js统一配置。 libs中通常会是一些开源的 js 库,如果示例只依赖 mars3d 相关资源,可省略libs字段。
{
  "name": "天地图地形",
  "main": "terrain/terrainTDT",
  "hasPannel": true,
  "libs": ["mars3d", "mars3d-tdt"],
  "thumbnail": "b10_terrain_tdt.jpg"
}

通过 includeLibs.js 中的 isLocal 变量,手动控制使用本地资源,还是 CDN 资源

  1. resources 依赖,一些个性化的资源,在开发过程中提取封装的文件的依赖资源,比如只是单个示例本身使用的一些js、css文件。
{
  "name": "POI兴趣点搜索(Cesium原生)",
  "main": "control/cesium/geocoder",
  "resources": ["cesiumControl.css"],
  "thumbnail": "d10_geocoder.jpg"
}

同级目录下只需要配置文件名,不在同级目录的 需配置打包后文件位置的绝对路径如 /example/graphic/apply/typhoon/Typhoon.js

添加新页面

publi/config/thumbnail.json

[
  {
    "name": "测试演示开发",
    "icon": "fa-globe",
    "download": true,
    "children": [
      {
        "name": "demo",
        "details": "demo演示",
        "children": [
          {
            "name": "demo1",
            "thumbnail": "demo.jpg",
            "main": "demo/demo1",
            "hasPannel": true
          }
        ]
      }
    ]
  },
  {
    "name": "快速开始",
    "icon": "fa-globe",
    "download": false,
    "children": [
      {
        "name": "创建三维场景",
        "details": "演示 new mars3d.Map() 构造场景时支持的一些参数",
        "children": [
          {
            "name": "demo1",
            "thumbnail": "demo.jpg",
            "main": "map/create/demo1"
          },
          {
            "name": "快速创建地球",
            "thumbnail": "map-create-options.jpg",
            "main": "map/create/options"
          },
          {
            "name": "根据配置文件创建地球",
            "thumbnail": "map-create-json.jpg",
            "main": "map/create/json"
          },

在src/example中添加页面
我这里添加了一个demo文件,有
src/example/demo/demo1/map.js
src/example/demo/demo1/index.vue
map.js:

import * as mars3d from "mars3d"

export let map // mars3d.Map三维地图对象

// 需要该接口来将js给cesium组件发送消息
export const eventTarget = new mars3d.BaseClass()


// 构造地图主方法【必须】
function initMap(options) {
  // 创建三维地球场景
  map = new mars3d.Map("mars3dContainer", options)
}
// 需要覆盖config.json中地图属性参数(当前示例框架中自动处理合并)
// export const mapOptions = {
//   scene: {
//     center: { lat: 30.468743, lng: 116.499464, alt: 67446, heading: 0, pitch: -45 }
//   }
// }
// /**
//  * 初始化地图业务,生命周期钩子函数(必须)
//  * 框架在地图初始化完成后自动调用该函数
//  * @param {mars3d.Map} mapInstance 地图对象
//  * @returns {void} 无
//  */
// export function onMounted(mapInstance) {
//   map = mapInstance // 记录首次创建的map
// }

// /**
//  * 释放当前地图业务的生命周期函数
//  * @returns {void} 无
//  */
// export function onUnmounted() {
//   map = null
// }


export function loginfo(text) {
  console.log(text)
}

export function drawdruis() {
  // 画矢量图形
  map.graphicLayer.startDraw({
    type: "rectangle",
    style: {
      color: "#007be6",
      opacity: 0.8,
      outline: false
    },
    success: function (graphic) {
      eventTarget.fire("drawgraphic", { graphicId: graphic.id })
    }
  })
}

index.vue:

<template>
  <!-- 这些本质都是将组件放到原生cesium的viewer的表面上-->
  <!-- 所以这部分的ui只负责些工具栏,和cesium主体没有直接交互,直接交互的是map.js -->
  <mars-dialog visible="true" right="10" top="10">
    <a-space>
      <mars-input v-model:value="text" :allowclear="true" @change="onTextChange" />
      <mars-button @click="onclickDraw">绘制</mars-button>
      <mars-input v-model:value="returnmsg" :allowclear="true" @change="onTextChange" />
    </a-space>
  </mars-dialog>
</template>

<script setup lang>
import { ref } from "vue"
import * as mapwork from "./map.js"
// 数据区
const text = ref("传递给后台js的数据")
const returnmsg = ref("等待后台js数据")
const onTextchange = function () {
  mapwork.loginfo(text.value)
}
// 点击画图之后,js就会画图然后将数据传入到eventTarget中,eventTarget一旦发现数据尝试,就会打印该数据
const onclickDraw = function () {
  mapwork.loginfo(text.value)
  mapwork.drawdruis()
}
mapwork.eventTarget.on("drawgraphic", function (e) {
  console.log(e)
  returnmsg.value = e.graphicId
})
</script>

单个示例的内部结构

每个示例都是一个单独的文件夹,均放在src\example示例目录下的子目录,因为示例众多,建议多级目录来管理。

示例相关文件

示例目录下,一般有2个文件(地图业务与UI解耦):

  • map.js文件:涉及地图业务的操作均写在 map.js 中;

  • index.vue 文件:是一个Vue组件面板,涉及 UI 层面、和地图无关的操作均写在 index.vue 中;

内部构流程图

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

image

5.3. map.jsindex.vue各自代码业务分离的原则

原则:

  • 涉及地图业务的操作均写在 map.js 中
  • 涉及 UI 层面、和地图无关的操作均写在 index.vue 中,vue 中不得使用 mars3d 和 Cesium 开头的类(组件中出除外)

如何区分?

  • 删除 index.vue 时不影响地图本身业务,map.js 需要正常运行 !!!
  • 删除 map.js 时,index.vue 需要正常展示 UI(除 mapWork 相关操作无响应外) !!!

阅读示例源码和调试学习

示例的目的是演示平台的每个功能点,可以按需求或兴趣去学习每一个示例,

  • (1)学习中可以查询相关类的 API 文档
  • (2)尝试修改源码中参数、方法等,来体验不同的呈现效果。

开发中常见问题

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

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

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

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

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

2. src\example\中增加的资源访问 404

因为新增静态资源涉及拷贝,需要重启服务 npm run serve

posted @ 2023-08-19 19:09  Coder-Wang  阅读(301)  评论(0编辑  收藏  举报