弹窗问题

8/26/2024

# 点击模型的信息弹出框内容想丰富一下

属性有 2 种存储方式

  1. 是存在数据库等其他地方,通过单击到的属性的 id 去取其他属性。
  2. 是转换数据时内置到模型中去(需要更加数据处理工具的相关教程操作)。
  3. 先绑定单击事件=》取数据=》showPopup 弹窗显示属性

# 模型能不能获取我们自定义的编号

绑定到 graphic 的 attr , 构造时传入 attr 属性

# 可以通过这种 tree 上有 id 值的情况,控制 3dtiles 模型中(max 或者 bim)某个部件的显隐吗

可以,style 控制的。TilesetLayer - Mars3D API 文档

image

# 3dtiles 模型中,能不能加个菜单,可以控制模型部分组件的显示隐藏

自行处理即可。可以参考这个示例代码。

image

# 面板想要配置可拖拽如何配置呢?

image

  1. 下载想要的示例全局搜索“可拖拽”三个字,示例的下载链接:

http://mars3d.cn/doc.html#project/example

image

  1. 找到关键字“draggable”,查看相关的 widget 参数说明。

示例路径:

  1. src\components\mars-ui\mars-dialog\index.vue 演示示例:
  2. id=graphic/video/video2D-flv

拖拽的效果 image

  1. 关于面板的参数控制均推荐上述步骤搜索使用参考示例,严格按照步骤进行开发实现业务效果。

# 关于 mars3d 的 widget 的相关设置没有详细 API 问题说明

  1. 首先申明:以前的 mard3d 的 widget 的 view.js 相关的 api 均是在原生技术栈下面方便大家使用封装的,保留使用 widget 模块化 方式,并不是指我们不用 vue 等现代化技术栈,而是具体按公司人员研发水平和技术栈情况按需选择,适合自己的才是最好的。

  2. 现在技术栈不停的更新迭代,我们也同步升级,弃用了以前的 widget 相关的 api。

  3. 封装的 andesign 组件库,大家也可以看看他们官方的文档

  4. Ant Design Vue — An enterprise-class UI components based on Ant Design and Vue.js

image

  1. 避免后期误解,mars3d-widget 我们正式弃用,原生项目中直接引入了对应 widget 源码,类似 vue 一样。具体说明可见 Mars3d 官网的版本更新日志。具体参考的话,可以详见示例代码的 mars3d/thirdParty/es5-widget/es5-widget.js 代码机制。

git clone https://gitee.com/marsgis/mars3d-es5-project.git

1
2
3

image

总结说明:目前 mars3d-widget 插件已弃用,原生 JS 技术栈下的项目 widget 中直接改为使用源码了(代码在示例和项目下的 mars3d/thirdParty/es5-widget/ 目录下), 对应 api 在\lib\mars3d\thirdParty\es5-widget\api.zip 文件中。

就是 3 个技术栈项目模版的 widget 相关机制和代码,目前均在项目本身的源码中,与 mars3d 不在有关系了。彻底开源了,大家可以自行研究。

# mars3d 基于 vue3.0 的 widget 使用

  1. mars3d 在 vue3.0 生态上开发了两个 gis 相关开源项目 mars3d-vue-example 和 mars3d-vue-project,在这两个项目中 widget 都是非常重要的一个模块。通过 widget 可以在复杂的场景下非常清晰的管理功能模块之间的互斥关系,管理内存,完成不同的功能模块之间的解耦,并且可以实现功能模块之间的交互。下面就来介绍一下,widget 模块的使用。

  2. 前置依赖: 使用 widget 模块,则必须依赖 vuex,通过 vuex 实现 widget 管理、交互等。

  3. widget 相关的代码一般会被放置在 src/widgets 目录下,按照功能或者业务来新建子目录管理 widget 代码,一般每个目录下的 index.vue 就是此 widget 的入口,通常也会包括一个 map.ts 文件用于编写地图相关代码。在某些特殊的场景下,也会将多个 vue 文件放置在同一个 widget 目录下,方便共享 map.ts 的命名空间,后面会针对这些特殊场景具体介绍。下面是一个标准的 widget 目录位置和结构:

image

import { defineAsyncComponent, markRaw } from "vue";
import { WidgetState } from "@mars/common/store/widget";
import { StoreOptions } from "vuex";

const store: StoreOptions<WidgetState> = {
  state: {
    // 自定义widget的默认值
    defaultOption: {},
    // widgets 配置列表
    widgets: [
      {
        // required widget使用的异步组件
        component: markRaw(
          defineAsyncComponent(() =>
            import("@mars/widgets/demo/menu/index.vue")
          )
        ),
        // required widget的唯一标识
        name: "menu",
        // 是否可以被自动关闭 default true
        autoDisable: false,
        // 此widget打开时,是否自动关闭其他可关闭的widget default true
        disableOther: false,
        /*
         * widget分组, widget打开时会强制关闭所有同组的其他widget
         * 优先级高于 disableOther autoDisable
         */
        group: "demo",
      },
    ],
    // 默认打开的widget
    openAtStart: ["menu"],
  },
};

export default store;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

WidgetState 接口定义如下:

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

export interface Widget {
  name: string // 唯一标识
  key?: string // 作为vue 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 // 支持配置默认参数
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

还需要在 main.ts 中初始化配置:

import { createApp } from "vue";
import Application from "./App.vue";
import { injectState, key } from "@mars/common/store/widget";
import { store as testStore, key as testKey } from "@mars/common/store/test";
import store from "./widget-store";

const app = createApp(Application);

// 此处传入key是为了让widget的store有自己的独立命名空间,不影响项目中的其他store
app.use(injectState(store), key);
// 项目中的其他store
app.use(testStore, testKey);

app.mount("#app");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  1. 完成上述配置工作之后,就可以编写具体的 widget 代码了,widget 本身其实就是一个 vue 组件,原则上只负责 ui 相关的展示和逻辑,地图相关的代码新建 map.ts 文件进行逻辑上的解耦,widget 提供了 api 来完成组件和 map 的交互。下面是一个标准的 widget 组件的基本结构。
<template>
 <mars-button class="small-btn" @click="onDraw">绘制</mars-button>
</template>

<script setup lang="ts">
import { onUnmounted, ref } from "vue"
import useLifecycle from "@mars/common/uses/use-lifecycle"
import * as mapWork from "./map"

// 激活map.ts生命周期
useLifecycle(mapWork)

const onClick = () => {
  // 调用 map.ts 中的方法
  mapWork.onDraw()
}
// 监听 map.ts 中抛出的事件,基于 mars3d.BaseClass 类实现
mapWork.eventTarget.on("drawExtent", function (event: any) {
  // 此处用于处理事件
  console.log(event)
})

onUnmounted(() => {
  // 销毁操作
})
</script>
<style lang="less"></style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  1. 上面代码中的 useLifecycle 是一个比较重要的 api,他接受 map.ts 的导出模块作为参数,建立了 vue 和 map.ts 生命周期的关联。可用的 map.ts 可用的生命周期为 onMounted 和 onUnmounted,map.ts 标准结构如下。
import * as mars3d from "mars3d";

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

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

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

// 释放当前业务
export function onUnmounted(): void {
  map.graphicLayer.clear();
  eventTarget = null;
  map = null;
}

// 绘制矩形(演示map.js与index.vue的交互)
export function onDraw(): 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 });
      // 抛出事件可以在vue中进行监听
      eventTarget.fire("drawExtent", { extent: JSON.stringify(rectangle) });
    },
  });
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
  1. 到此我们就初步了解了 widget 的使用,具体使用包括和 marsui 搭配使用、参数配置、动态传参、api、多个根组件场景的处理、widget 间的动态交互等。

参考:https://blog.csdn.net/m0_69803146/article/details/128152128?spm=1001.2014.3001.5502

最后更新: 9/29/2024, 4:05:58 PM