Преглед изворни кода

2DInsert <feat>:新增2D平面图编辑器;

YaolongHan пре 4 година
родитељ
комит
30ce248dd4

+ 364 - 0
docs/.vuepress/components/2DInsert/getStart.vue

@@ -0,0 +1,364 @@
+<!-- 画板 -->
+<template>
+  <div ref="baseMap" class="base-map">
+    <canvas
+      id="floorMap"
+      :width="canvasWidth"
+      :height="canvasHeight"
+      tabindex="0"
+    ></canvas>
+  </div>
+</template>
+<script>
+import { SGraphScene } from "@persagy-web/graph/lib";
+import { SGraphView, SGraphSvgItem } from "@persagy-web/graph";
+import { SFloorParser, getJsonz } from "@persagy-web/big/lib";
+import { SZoneParser } from "@persagy-web/big";
+
+export default {
+  props: {
+    // 是否展示大小控制器
+    hasShowContro: {
+      type: Boolean,
+      default: true,
+      required: false,
+    },
+    // //// 关于底图
+
+    // 一,展示底图的元素
+    // 3.是否展示柱子
+    isShowColumn: {
+      type: Boolean,
+      default: false,
+      required: false,
+    },
+    // 4.是否展示墙
+    isShowWall: {
+      type: Boolean,
+      default: false,
+      required: false,
+    },
+    // 5.是否展示虚拟墙
+    isShowVirtualWall: {
+      type: Boolean,
+      default: false,
+      required: false,
+    },
+    // 6.是否展示门
+    isShowDoor: {
+      type: Boolean,
+      default: false,
+      required: false,
+    },
+    // 7.是否展窗户
+    isShowWindow: {
+      type: Boolean,
+      default: false,
+      required: false,
+    },
+    // 8.是否显示空间
+    isSpaceSelectable: {
+      type: Boolean,
+      default: true,
+      required: false,
+    },
+    // 是否展示底图名称
+    showBaseName: {
+      type: Boolean,
+      default: false,
+      required: false,
+    },
+  },
+  data() {
+    return {
+      canvasWidth: 0, // 画布的宽
+      canvasHeight: 0, // 画布的高
+      view: null, // 视图 view
+      scene: null, // 场景类
+    };
+  },
+  methods: {
+    // 初始化
+    init() {
+      this.clearImg();
+      this.view ? (this.view.scene = this.scene) : null;
+      // 获取压缩包数据并解压
+      this.getMapBlob();
+    },
+    // 选中图例
+    emitChoice(itemList) {
+      this.$emit("emitChoice", itemList);
+      this.choiceListLength = itemList.length;
+    },
+    // 鼠标点击画板事件
+    vueOnMouseDown(e) {
+      // 如果为非拖动操作方可执行点击事件
+      if (!this.view.isDrag) {
+        this.$emit("vueOnMouseDown", e);
+        // 是否需要打点(必须在空间内)
+        // setTimeout 用于让选中事件先于vue 点击
+        setTimeout(() => {
+          if (this.choiceListLength) {
+            if (
+              (typeof this.SetNewMarkConfig == "boolean" &&
+                this.SetNewMarkConfig == true) ||
+              typeof this.SetNewMarkConfig == "object"
+            ) {
+              this.setNewMark(e, this.SetNewMarkConfig);
+            }
+          }
+        }, 100);
+      }
+    },
+    // 请求获取地图的压缩包
+    getMapBlob() {
+      const url = this.mapUrl + this.dataKey;
+      getJsonz(url).then((data) => {
+        // 解析数据并放入压缩包中
+        this.parserData(data);
+      });
+    },
+    // 解析数据并注入 scene 类中
+    parserData(data) {
+      let parser = new SFloorParser();
+      parser.parseData(data);
+      parser.spaceList.forEach((t) => {
+        //是否显示空间
+        t.visible = this.isSpaceSelectable;
+        //设置样式
+        t.style = this.baseMapStyle;
+        //是否展示名称
+        t.showBaseName = this.showBaseName;
+        // 是否可选
+        t.selectable = true;
+        t.connect("onMouseDown", this, this.clickSpaceItem);
+
+        // 添加图例
+        this.scene.addItem(t);
+      });
+      parser.wallList.forEach((t) => {
+        //是否显示
+        t.visible = this.isShowWall;
+        // 是否可选
+        t.selectable = true;
+        this.scene.addItem(t);
+      });
+      parser.virtualWallList.forEach((t) => {
+        //是否显示
+        t.visible = this.isShowVirtualWall;
+        // 是否可选
+        t.selectable = true;
+        this.scene.addItem(t);
+      });
+      parser.doorList.forEach((t) => {
+        //是否显示
+        t.visible = this.isShowDoor;
+        // 是否可选
+        t.selectable = true;
+        this.scene.addItem(t);
+      });
+      parser.columnList.forEach((t) => {
+        //是否显示
+        t.visible = this.isShowColumn;
+        // 是否可选
+        t.selectable = true;
+        this.scene.addItem(t);
+      });
+      parser.casementList.forEach((t) => {
+        //是否显示
+        t.visible = this.isShowWindow;
+        // 是否可选
+        t.selectable = true;
+        this.scene.addItem(t);
+      });
+      // 画板是否可拖动
+      this.view.DragMove = true;
+      this.view.fitSceneToView();
+    },
+    // 图片缩小
+    changeSize(isbiger) {
+      if (isbiger) {
+        this.view.scaleByPoint(
+          (this.view.scale * 1.1) / this.view.scale,
+          this.canvasWidth / 2,
+          this.canvasHeight / 2
+        );
+      } else {
+        this.view.scaleByPoint(
+          (this.view.scale * 0.9) / this.view.scale,
+          this.canvasWidth / 2,
+          this.canvasHeight / 2
+        );
+      }
+    },
+    // 鼠标移入
+    mouseEnter(item, e) {
+      if (item.data.ElementType == "Mark") {
+        item.status = "highlight";
+      }
+      this.$emit("mouseEnter", item, e);
+    },
+    // 鼠标移出
+    mouseLeave(item, e) {
+      if (item.data.ElementType == "Mark") {
+        item.status = "default";
+      }
+      this.$emit("mouseLeave", e, item);
+    },
+    // 点击item
+    clickSpaceItem(item, e) {
+      console.log(item, e);
+      this.$emit("clickSpaceItem", e, item);
+    },
+    // 点击item
+    clickEquipItem(item, e) {
+      this.$emit("clickEquipItem", e, item);
+    },
+
+    // 解析设备点
+    mapEquipment(val) {
+      this.scene ? this.scene.clearEquip() : "";
+      const EqParse = new EquipmentParser(new EquipmentFactory());
+      const markList = [];
+      val.forEach((item) => {
+        if (item.bimLocation) {
+          const arr = item.bimLocation.split(",");
+          const mark = {
+            Id: item.equipId,
+            ElementType: "Mark",
+            equipId: item.equipId,
+            Name: item.equipName,
+            x: Number(arr[0]),
+            y: Number(arr[1]),
+            width: item.width,
+            height: item.height,
+            imgSource: item.imgSource,
+            textObj: item.textObj ? item.textObj : null,
+            tooltipMsg: item.tooltipMsg || [],
+          };
+          markList.push(mark);
+        }
+      });
+      EqParse.parseData(markList);
+      EqParse.markList.forEach((item) => {
+        item.style = this.equipStyle;
+        item.status = "disabled"; // 更具状态展示不同的效果;
+        item.connect("mouseEnter", this, this.mouseEnter);
+        item.connect("mouseLeave", this, this.mouseLeave);
+        item.connect("click", this, this.clickEquipItem);
+
+        this.scene.addItem(item);
+      });
+      this.scene.equipItemList = EqParse.markList;
+    },
+    // 解析业务空间
+    mapSpace(val) {
+      this.scene ? this.scene.clearSpace() : "";
+      const parse = new SZoneParser();
+      parse.parseData(val);
+      parse.zoneList.forEach((item) => {
+        item.connect("click", this, this.clickSpaceItem);
+        this.scene.addItem(item);
+      });
+      this.scene.zoonItemList = parse.markList;
+    },
+    // 清空画布
+    clearImg() {
+      this.scene = new FloorScene();
+      this.scene.emitChoice = this.emitChoice;
+      this.scene.vueOnMouseDown = this.vueOnMouseDown;
+      if (this.view) {
+        this.view.update();
+      }
+    },
+    // 打点操作
+    setNewMark(e, markConfig) {
+      let markWidth = 30;
+      let markHeight = 30;
+      // // 是否需要自定义mark
+      if (typeof markConfig == "object") {
+        markWidth = Number(markConfig.width) ? Number(markConfig.width) : 30;
+        markHeight = Number(markConfig.height) ? Number(markConfig.height) : 30;
+      }
+      let mark = null;
+      if (this.newMarkList.length) {
+        mark = this.newMarkList[0];
+        mark.x = e.x;
+        mark.y = e.y;
+      } else {
+        // 有且只有一个mark
+        const EqParse = new EquipmentParser(new EquipmentFactory());
+        mark = {
+          Id: new Date(),
+          Name: "",
+          width: markWidth,
+          height: markHeight,
+          x: e.x,
+          y: e.y,
+        };
+        EqParse.parseData([mark]);
+        EqParse.markList.forEach((item) => {
+          item.style = this.equipStyle;
+          this.scene.addItem(item);
+          this.newMarkList.push(item);
+        });
+      }
+      this.$emit("setNewMark", e);
+    },
+  },
+  watch: {
+    // 监听空间数组
+    zoneList: {
+      handler(val) {
+        if (val && val.length) {
+          this.mapSpace(val);
+        }
+      },
+      deep: true,
+    },
+    // 监听设备数组
+    equipmentList: {
+      handler(val) {
+        if (val && val.length) {
+          this.mapEquipment(val);
+        }
+      },
+      deep: true,
+    },
+    // 监听key
+    dataKey: {
+      handler(val) {
+        if (val) {
+          this.init();
+        }
+      },
+      immediate: true,
+    },
+  },
+  created() {
+    this.clearImg();
+  },
+  mounted() {
+    // 获取 canvas 的宽高
+    this.canvasWidth = this.$refs.baseMap.offsetWidth;
+    this.canvasHeight = this.$refs.baseMap.offsetHeight;
+    // 初始化场景类
+    this.view = new FloorView("floorMap");
+    if (this.scene) {
+      this.view.scene = this.scene;
+    }
+  },
+};
+</script>
+<style lang="less" scoped>
+.base-map {
+  width: 100%;
+  height: 100%;
+  position: relative;
+  .sacle-btn {
+    position: absolute;
+    right: 0;
+    bottom: 0;
+  }
+}
+</style>

+ 25 - 0
docs/guides/2DInsert/brief.md

@@ -0,0 +1,25 @@
+为方便开发同事能够快速引入2D平面图相关模块、并针对自身项目进行二次开发遂提供此文档。
+1. 引擎相关库采用的是面向对象编程;采用的是typeScript语言;
+2. 引擎是基于canvas api封装以及开发的工具包、分为
+ ```
+    "@persagy-web/base",
+    "@persagy-web/big",
+    "@persagy-web/draw",
+    "@persagy-web/graph",
+    "@persagy-web/edit",
+    "@persagy-web/big-edit",
+ ```
+ 其中用于嵌入展示的相关类为
+ ```
+    "@persagy-web/base",
+    "@persagy-web/big",
+    "@persagy-web/draw",
+    "@persagy-web/graph",
+ ```
+
+::: warning
+3. 如果项目中有相关派生类、强烈推荐用 typescript 开发、如不支持typescript 建议在开发中直接实时编译;
+:::
+::: danger
+4. 本引擎尚未验证在 IE11 以及 IE11 以下的稳定性、暂不支持该兼容性。
+:::

+ 1 - 0
docs/guides/2DInsert/get-start.md

@@ -0,0 +1 @@
+## 快速上手

+ 22 - 0
docs/guides/2DInsert/install.md

@@ -0,0 +1,22 @@
+## 介绍:
+为防止公司代码剽窃、图形绘制引擎包以 npm 包的形式部署在了公司私有服务器上;所以在下载时、需要先下载其他依赖包;然后将 npm 指向私服;再下载引擎包;
+## 安装
+1. 安装项目其他依赖包
+2. 改变 npm 指向
+```
+ npm config set registry http://dev.dp.sagacloud.cn:8082/repository/npm-saga/
+```
+3. 下载依赖包
+```
+    "@persagy-web/base": "2.2.1",
+    "@persagy-web/big": "2.2.18",
+    "@persagy-web/draw": "2.2.8",
+    "@persagy-web/graph": "2.2.22",
+```
+4. 将npm 指向改回原来指向
+```
+npm config set registry https://registry.npmjs.org/
+```
+::: warning
+建议公共包与私有包按照上述步骤分开下载;如果一起下载会引发问题
+:::

+ 15 - 6
docs/guides/index.js

@@ -65,6 +65,7 @@ const content = [
             {
                 title: "Item 示例",
                 children: [
+                    ["/guides/big/items/wall", "简介"],
                     ["/guides/big/items/wall", "墙"],
                     ["/guides/big/items/column", "柱子"],
                     ["/guides/big/items/door", "门"],
@@ -82,12 +83,20 @@ const content = [
             ["/guides/big/mapDemo", "楼层平面图范例"],
         ]
     },
-    // {
-    //     title: "系统图",
-    //     children: [
-    //         ["/guides/system-diagram/json-file", "json数据格式"]
-    //     ]
-    // },
+    {
+        title: "平面图嵌入指南",
+        children: [
+            ["/guides/2DInsert/brief.md", "简介"],
+            ["/guides/2DInsert/install.md", "安装"],
+            ["/guides/2DInsert/install.md", "快速上手"],
+            ["/guides/2DInsert/install.md", "展示空间"],
+            ["/guides/2DInsert/install.md", "展示图"],
+            ["/guides/2DInsert/install.md", "相关事件"],
+            ["/guides/2DInsert/install.md", "修改图例属性"],
+            ["/guides/2DInsert/install.md", "派生类"],
+            ["/guides/2DInsert/install.md", "其他"],
+        ]
+    },
     {
         title: "编辑器",
         path: "/guides/edit/",

+ 3 - 2
package.json

@@ -13,16 +13,17 @@
     "lint": "eslint docs/**/*.{js,ts,tsx}"
   },
   "dependencies": {
+    "@persagy-vue/doc": "1.1.36",
     "@persagy-web/base": "2.2.1",
     "@persagy-web/big": "2.2.18",
     "@persagy-web/draw": "2.2.8",
     "@persagy-web/graph": "2.2.22",
-    "@persagy-vue/doc": "1.1.36",
     "axios": "^0.19.2",
     "element-ui": "^2.12.0",
     "vue": "^2.6.10",
+    "vue-class-component": "^7.0.2",
     "vue-property-decorator": "^8.4.2",
-    "vue-class-component": "^7.0.2"
+    "vue-server-renderer": "^2.6.10"
   },
   "devDependencies": {
     "@typescript-eslint/eslint-plugin": "^2.33.0",