浏览代码

fix: 四川大厦地图数据处理

chenzhen2 2 年之前
父节点
当前提交
366ea2a614
共有 3 个文件被更改,包括 592 次插入13 次删除
  1. 10 0
      src/router/index.ts
  2. 194 13
      src/views/mapDataNew/index.vue
  3. 388 0
      src/views/mapDataNew/sichuan.vue

+ 10 - 0
src/router/index.ts

@@ -193,6 +193,16 @@ export const constantRoutes: Array<RouteRecordRaw> = [
       color: '#F5F5F5',
       hideHeader: false
     }
+  },
+  {
+    path: '/map-sichuan',
+    component: () => import('@/views/mapDataNew/sichuan.vue'),
+    name: 'map-sichuan',
+    meta: {
+      title: '四川大厦地图',
+      color: '#F5F5F5',
+      hideHeader: false
+    }
   }
 ]
 

+ 194 - 13
src/views/mapDataNew/index.vue

@@ -1,5 +1,19 @@
 <template>
   <div class="com-upload" style="position: relative">
+    <van-search
+      v-model="spaceName"
+      placeholder="请输入搜索关键词"
+      @update:model-value="searchSpace"
+    />
+    <div class="search-bt" style="position: fixed; right: 20px; top: 80px">
+      <div @click="zommAdd" style="display: inline-block; font-size: 30px">
+        <van-icon name="add-o" color="#1989fa" />
+      </div>
+      <div @click="zommDel" style="display: inline-block; font-size: 30px">
+        <van-icon name="minus" color="#1989fa" />
+      </div>
+    </div>
+
     <canvas id="myCanvas" class="canvasDom">
       <img
         :style="{ left: item.deviceArr[0].left, top: item.deviceArr[0].top }"
@@ -21,30 +35,82 @@
 </template>
     
   <script lang="ts">
+import { Search } from "vant";
 import { number } from "echarts";
 import { getMapInfo } from "@/apis/envmonitor";
 import { defineComponent, nextTick, onMounted, reactive, toRefs } from "vue";
 import { parseImgUrl } from "@/utils";
 
 export default defineComponent({
-  components: {},
+  components: {
+    VanSearch: Search,
+  },
   setup() {
     let spaceList: any = [];
+    let ctx: any = {};
+    let centerObj: any = {};
     const proxyData = reactive({
       spaceList: spaceList,
       parseImgUrl: parseImgUrl,
+      spaceName: "",
       width: 100,
       height: 200,
+      scale: 1,
+      ctx: ctx,
+      centerObj: centerObj,
+      // 搜索某个空间
+      searchSpace() {
+        proxyData.spaceList.map((item: any) => {
+          // debugger
+          console.log(item.localName == proxyData.spaceName);
+          console.log("搜索====");
+          console.log(item.localName);
+          console.log(proxyData.spaceName);
+          if (item.localName == proxyData.spaceName) {
+            console.log("搜索到某个空间");
+            item.fillColor = "red";
+            item.shadow = true;
+            proxyData.initCanvas();
+          } else {
+            // item.shadow = false;
+            // item.fillColor = "#ececec";
+          }
+        });
+      },
+      // 放大
+      zommAdd() {
+        console.log("被点击了");
+        if (proxyData.scale > 3) {
+          return;
+        }
+        proxyData.scale = proxyData.scale + 0.1;
+        // debugger;
+        proxyData.initCanvas();
+      },
+      // 缩小
+      zommDel() {
+        if (proxyData.scale < 0.3) {
+          return;
+        }
+        proxyData.scale = proxyData.scale - 0.1;
+        proxyData.initCanvas();
+      },
       // canvas画图
       initCanvas() {
         let canvasDom: any = document.querySelector("#myCanvas");
-        canvasDom.width = proxyData.width;
-        canvasDom.height = proxyData.height;
+        canvasDom.width = proxyData.width * proxyData.scale;
+        canvasDom.height = proxyData.height * proxyData.scale;
         let ctx: any = canvasDom.getContext("2d");
+        proxyData.ctx = ctx;
         ctx.clearRect(0, 0, proxyData.width, proxyData.height);
+        ctx.scale(proxyData.scale, proxyData.scale, centerObj.left, centerObj.top);
         proxyData.spaceList.map((item: any) => {
           let left: any = parseInt(item.left);
           let top: any = parseInt(item.top);
+          if (item.localName == "会议室-1") {
+            proxyData.centerObj = item;
+          }
+
           let pointArr: any = [
             {
               left: left,
@@ -80,28 +146,53 @@ export default defineComponent({
           let logoArr: any = [
             {
               left: left + item.width / 2,
-              top: top + item.top / 2,
+              top: top + item.height / 2,
             },
             {
               left: left + item.width / 2 + 30,
-              top: top + item.top / 2 + 30,
+              top: top + item.height / 2 + 30,
             },
           ];
           item.pointArr = pointArr;
           item.deviceArr = deviceArr;
           item.logoArr = logoArr;
-          //   images/map-icon/bg_disable.png
+
           if (item.canClick) {
-            ctx.lineWidth = 1;
             ctx.beginPath();
+            ctx.fillStyle = item.fillColor;
             pointArr.map((item: any, index: any) => {
-              ctx.lineTo(item.left, item.top);
+              if (index == 0) {
+                ctx.moveTo(item.left, item.top);
+              } else {
+                ctx.lineTo(item.left, item.top);
+              }
             });
-            ctx.fillStyle = "#cfefef";
-            ctx.fill();
             proxyData.drawIcon(ctx, "coffee.svg", deviceArr[0]);
             proxyData.drawIcon(ctx, "dev.svg", deviceArr[1]);
             proxyData.drawIcon(ctx, "deviceroom.svg", deviceArr[2]);
+            ctx.closePath();
+            ctx.fill();
+            ctx.lineWidth = 1;
+            ctx.strokeStyle = "rgba(15, 206, 233, 1)";
+            ctx.stroke();
+
+            ctx.beginPath();
+            ctx.font = "12px serif";
+            ctx.textAlign = "center";
+            ctx.fillStyle = item.fillColor !== "#ececec" ? "#ffffff" : "red";
+            ctx.fillText(
+              item.localName,
+              item.logoArr[0].left,
+              item.logoArr[0].top,
+              item.width
+            );
+            ctx.closePath();
+            if (item.shadow) {
+              item.shadowColor = "#000000";
+              ctx.shadowOffsetX = -50; //阴影x轴位移。正值向右,负值向左。
+              ctx.shadowOffsetY = -50; //阴影y轴位移。正值向下,负值向上。
+              ctx.shadowBlur = 10; //阴影模糊滤镜。数据越大,扩散程度越大。
+            }
           } else {
             let img: any = new Image();
             img.src = require("@/assets/svg/bg_disable.png");
@@ -138,9 +229,12 @@ export default defineComponent({
           // proxyData.initCanvas();
           console.log(event);
           // alert("点击了!");
-          proxyData.spaceList.map((item: any) => {
+          for (let i = 0; i < proxyData.spaceList.length; i++) {
+            let item: any = proxyData.spaceList[i];
             let deviceArr: any = item.deviceArr;
-            deviceArr.map((dev: any,index:any) => {
+            let pointArr: any = item.pointArr;
+            let iconFlag: any = false;
+            deviceArr.map((dev: any, index: any) => {
               if (
                 x >= dev.left &&
                 x <= dev.left + 15 &&
@@ -149,11 +243,84 @@ export default defineComponent({
               ) {
                 // alert("我被点了!");
                 // console.log("我被点了!")
+                iconFlag = true;
                 alert(`我被点了设备图标!${index}`);
               }
             });
-          });
+            if (iconFlag) {
+              break;
+            }
+            let dot: any = {
+              x: x,
+              y: y,
+            };
+            let coordinates: any = pointArr;
+            let flag = proxyData.judge(dot, coordinates, 1);
+            // console.log(flag);
+            if (flag) {
+              alert("点击了区域" + item.localName);
+              break;
+            }
+          }
+        }
+      },
+      judge(dot: any, coordinates: any, noneZeroMode: any) {
+        // 默认启动none zero mode
+        noneZeroMode = noneZeroMode || 1;
+        let x: any = dot.x,
+          y: any = dot.y;
+        let crossNum: any = 0;
+        // 点在线段的左侧数目
+        let leftCount: any = 0;
+        // 点在线段的右侧数目
+        let rightCount: any = 0;
+        for (let i = 0; i < coordinates.length - 1; i++) {
+          let start: any = coordinates[i];
+          let end: any = coordinates[i + 1];
+          start.x = start.left;
+          start.y = start.top;
+          end.x = end.left;
+          end.y = end.top;
+
+          // 起点、终点斜率不存在的情况
+          if (start.x === end.x) {
+            // 因为射线向右水平,此处说明不相交
+            if (x > start.x) continue;
+
+            // 从左侧贯穿
+            if (end.y > start.y && y >= start.y && y <= end.y) {
+              leftCount++;
+              crossNum++;
+            }
+            // 从右侧贯穿
+            if (end.y < start.y && y >= end.y && y <= start.y) {
+              rightCount++;
+              crossNum++;
+            }
+            continue;
+          }
+          // 斜率存在的情况,计算斜率
+          let k = (end.y - start.y) / (end.x - start.x);
+          // 交点的x坐标
+          let x0 = (y - start.y) / k + start.x;
+          // 因为射线向右水平,此处说明不相交
+          if (x > x0) continue;
+
+          if (end.x > start.x && x0 >= start.x && x0 <= end.x) {
+            crossNum++;
+            if (k >= 0) leftCount++;
+            else rightCount++;
+          }
+          if (end.x < start.x && x0 >= end.x && x0 <= start.x) {
+            crossNum++;
+            if (k >= 0) rightCount++;
+            else leftCount++;
+          }
         }
+
+        return noneZeroMode === 1
+          ? leftCount - rightCount !== 0
+          : crossNum % 2 === 1;
       },
       drawIcon(ctx: any, url: any, iconPerstion: any) {
         let img: any = new Image();
@@ -162,6 +329,19 @@ export default defineComponent({
           ctx.drawImage(img, iconPerstion.left, iconPerstion.top, 20, 10);
         };
       },
+      // 设置区域颜色
+      setSpaceColor() {
+        proxyData.spaceList.map((item: any, index: any) => {
+          if (index % 2 == 0) {
+            item.fillColor = "#ffcc33";
+          } else if (index % 3 == 0) {
+            item.fillColor = "#ccff99";
+          } else {
+            item.fillColor = "#ececec";
+          }
+        });
+        console.log(proxyData.spaceList);
+      },
       /**
        * 获取地图信息
        */
@@ -178,6 +358,7 @@ export default defineComponent({
             proxyData.width = data.width;
             proxyData.height = data.height;
             proxyData.spaceList = data.spaceList;
+            proxyData.setSpaceColor();
             proxyData.initCanvas();
           })
           .catch(() => {});

+ 388 - 0
src/views/mapDataNew/sichuan.vue

@@ -0,0 +1,388 @@
+<template>
+  <div class="com-upload" style="position: relative">
+    <van-search
+      v-model="spaceName"
+      placeholder="请输入搜索关键词"
+      @update:model-value="searchSpace"
+    />
+    <div class="search-bt" style="position: fixed; right: 20px; top: 80px">
+      <div @click="zommAdd" style="display: inline-block; font-size: 30px">
+        <van-icon name="add-o" color="#1989fa" />
+      </div>
+      <div @click="zommDel" style="display: inline-block; font-size: 30px">
+        <van-icon name="minus" color="#1989fa" />
+      </div>
+    </div>
+
+    <canvas id="myCanvas" class="canvasDom" style="boder: 1px solid red">
+      <img
+        :style="{ left: item.deviceArr[0].left, top: item.deviceArr[0].top }"
+        style="
+          position: absolute;
+          width: 20px;
+          height: 20px;
+          z-index: 999;
+          left: 20px;
+          top: 20px;
+        "
+        :src="parseImgUrl('map-icon', 'device.svg')"
+        alt=""
+        :key="index"
+        v-for="(item, index) in spaceList"
+      />
+    </canvas>
+  </div>
+</template>
+      
+    <script lang="ts">
+import { Search } from "vant";
+import { number } from "echarts";
+import { getMapInfo } from "@/apis/envmonitor";
+import { defineComponent, nextTick, onMounted, reactive, toRefs } from "vue";
+import { parseImgUrl } from "@/utils";
+
+export default defineComponent({
+  components: {
+    VanSearch: Search,
+  },
+  setup() {
+    let spaceList: any = [];
+    let ctx: any = {};
+    let centerObj: any = {};
+    const proxyData = reactive({
+      spaceList: spaceList,
+      parseImgUrl: parseImgUrl,
+      spaceName: "",
+      width: 4327.5,
+      height: 3078.75,
+      scale: 1,
+      ctx: ctx,
+      centerObj: centerObj,
+      // 搜索某个空间
+      searchSpace() {
+        proxyData.spaceList.map((item: any) => {
+          // debugger
+          console.log(item.localName == proxyData.spaceName);
+          console.log("搜索====");
+          console.log(item.localName);
+          console.log(proxyData.spaceName);
+          if (item.localName == proxyData.spaceName) {
+            console.log("搜索到某个空间");
+            item.fillColor = "red";
+            item.shadow = true;
+            proxyData.initCanvas();
+          } else {
+            // item.shadow = false;
+            // item.fillColor = "#ececec";
+          }
+        });
+      },
+      // 放大
+      zommAdd() {
+        console.log("被点击了");
+        if (proxyData.scale > 3) {
+          return;
+        }
+        proxyData.scale = proxyData.scale + 0.1;
+        // debugger;
+        proxyData.initCanvas();
+      },
+      // 缩小
+      zommDel() {
+        if (proxyData.scale < 0.3) {
+          return;
+        }
+        proxyData.scale = proxyData.scale - 0.1;
+        proxyData.initCanvas();
+      },
+      // canvas画图
+      initCanvas() {
+        let canvasDom: any = document.querySelector("#myCanvas");
+        canvasDom.width = proxyData.width;
+        canvasDom.height = proxyData.height;
+        let ctx: any = canvasDom.getContext("2d");
+        proxyData.ctx = ctx;
+        ctx.clearRect(0, 0, proxyData.width, proxyData.height);
+        ctx.scale(
+          proxyData.scale,
+          proxyData.scale,
+          centerObj.left,
+          centerObj.top
+        );
+
+        proxyData.spaceList.map((item: any) => {
+          if (item.localName == "会议室-1") {
+            proxyData.centerObj = item;
+          }
+          console.log(item);
+          if (item.canClick) {
+            ctx.beginPath();
+            ctx.fillStyle = item.fillColor;
+            item.pointArr.map((childItem: any, index: any) => {
+              // debugger
+              childItem.left = childItem.left;
+              childItem.top = childItem.top;
+              if (index == 0) {
+                ctx.moveTo(childItem.left, childItem.top);
+              } else {
+                ctx.lineTo(childItem.left, childItem.top);
+              }
+            });
+            proxyData.drawIcon(ctx, "coffee.svg", item.deviceArr[0]);
+            proxyData.drawIcon(ctx, "dev.svg", item.deviceArr[1]);
+            proxyData.drawIcon(ctx, "deviceroom.svg", item.deviceArr[2]);
+            ctx.closePath();
+            ctx.fill();
+            ctx.lineWidth = 1;
+            ctx.strokeStyle = "rgba(15, 206, 233, 1)";
+            ctx.stroke();
+
+            ctx.beginPath();
+            ctx.font = "10px serif";
+            ctx.textAlign = "center";
+            ctx.fillStyle = item.fillColor !== "#ececec" ? "#ffffff" : "red";
+            ctx.fillText(
+              item.localName,
+              item.logoArr[0].left,
+              item.logoArr[0].top,
+              item.width
+            );
+            ctx.closePath();
+            if (item.shadow) {
+              item.shadowColor = "#000000";
+              ctx.shadowOffsetX = -50; //阴影x轴位移。正值向右,负值向左。
+              ctx.shadowOffsetY = -50; //阴影y轴位移。正值向下,负值向上。
+              ctx.shadowBlur = 10; //阴影模糊滤镜。数据越大,扩散程度越大。
+            }
+          } else {
+            let img: any = new Image();
+            img.src = require("@/assets/svg/bg_disable.png");
+            img.onload = function () {
+              ctx.beginPath();
+              item.pointArr.map((item: any, index: any) => {
+                if (index === 0) {
+                  ctx.moveTo(item.left, item.top);
+                } else {
+                  ctx.lineTo(item.left, item.top);
+                }
+              });
+              //   ctx.fillStyle = "#cfefef";
+              //   ctx.fill();
+              let pat: any = ctx.createPattern(img, "repeat");
+              ctx.fillStyle = pat;
+              ctx.fill();
+              ctx.closePath();
+              ctx.strokeStyle = "rgba(15, 206, 233, 1)";
+              ctx.stroke();
+            };
+          }
+        });
+      },
+      // 绑定事件
+      bindEvent() {
+        let canvasDom: any = document.querySelector("#myCanvas");
+        // 点击事件
+        canvasDom.addEventListener("click", detect);
+        function detect(event: any) {
+          let x: any = event.clientX - canvasDom.getBoundingClientRect().left;
+          let y: any = event.clientY - canvasDom.getBoundingClientRect().top;
+          //   let ctx: any = canvasDom.getContext("2d");
+          // proxyData.initCanvas();
+          console.log(event);
+          // alert("点击了!");
+          for (let i = 0; i < proxyData.spaceList.length; i++) {
+            let item: any = proxyData.spaceList[i];
+            let deviceArr: any = item.deviceArr;
+            let pointArr: any = item.pointArr;
+            let iconFlag: any = false;
+            deviceArr.map((dev: any, index: any) => {
+              if (
+                x >= dev.left &&
+                x <= dev.left + 15 &&
+                y >= dev.top &&
+                y < dev.top + 15
+              ) {
+                // alert("我被点了!");
+                // console.log("我被点了!")
+                iconFlag = true;
+                alert(`我被点了设备图标!${index}`);
+              }
+            });
+            if (iconFlag) {
+              break;
+            }
+            let dot: any = {
+              x: x,
+              y: y,
+            };
+            let coordinates: any = pointArr;
+            let flag = proxyData.judge(dot, coordinates, 1);
+            // console.log(flag);
+            if (flag) {
+              alert("点击了区域" + item.localName);
+              break;
+            }
+          }
+        }
+      },
+      judge(dot: any, coordinates: any, noneZeroMode: any) {
+        // 默认启动none zero mode
+        noneZeroMode = noneZeroMode || 1;
+        let x: any = dot.x,
+          y: any = dot.y;
+        let crossNum: any = 0;
+        // 点在线段的左侧数目
+        let leftCount: any = 0;
+        // 点在线段的右侧数目
+        let rightCount: any = 0;
+        for (let i = 0; i < coordinates.length - 1; i++) {
+          let start: any = coordinates[i];
+          let end: any = coordinates[i + 1];
+          start.x = start.left;
+          start.y = start.top;
+          end.x = end.left;
+          end.y = end.top;
+
+          // 起点、终点斜率不存在的情况
+          if (start.x === end.x) {
+            // 因为射线向右水平,此处说明不相交
+            if (x > start.x) continue;
+
+            // 从左侧贯穿
+            if (end.y > start.y && y >= start.y && y <= end.y) {
+              leftCount++;
+              crossNum++;
+            }
+            // 从右侧贯穿
+            if (end.y < start.y && y >= end.y && y <= start.y) {
+              rightCount++;
+              crossNum++;
+            }
+            continue;
+          }
+          // 斜率存在的情况,计算斜率
+          let k = (end.y - start.y) / (end.x - start.x);
+          // 交点的x坐标
+          let x0 = (y - start.y) / k + start.x;
+          // 因为射线向右水平,此处说明不相交
+          if (x > x0) continue;
+
+          if (end.x > start.x && x0 >= start.x && x0 <= end.x) {
+            crossNum++;
+            if (k >= 0) leftCount++;
+            else rightCount++;
+          }
+          if (end.x < start.x && x0 >= end.x && x0 <= start.x) {
+            crossNum++;
+            if (k >= 0) rightCount++;
+            else leftCount++;
+          }
+        }
+
+        return noneZeroMode === 1
+          ? leftCount - rightCount !== 0
+          : crossNum % 2 === 1;
+      },
+      drawIcon(ctx: any, url: any, iconPerstion: any) {
+        let img: any = new Image();
+        img.src = require(`@/assets/svg/${url}`);
+        img.onload = function () {
+          ctx.drawImage(img, iconPerstion.left, iconPerstion.top, 30, 20);
+        };
+      },
+      // 设置区域颜色
+      setSpaceColor() {
+        proxyData.spaceList.map((item: any, index: any) => {
+          if (index % 2 == 0) {
+            item.fillColor = "#ffcc33";
+          } else if (index % 3 == 0) {
+            item.fillColor = "#ccff99";
+          } else {
+            item.fillColor = "#ececec";
+          }
+        });
+        console.log(proxyData.spaceList);
+      },
+      /**
+       * 获取地图信息
+       */
+      getMapInfo() {
+        let params: any = {
+          projectId: "Pj1101080259",
+          floorId: "Fl11010802593241ec348ecb4148806b9034c8957454",
+        };
+        getMapInfo(params)
+          .then((res) => {
+            // debugger
+            let resData: any = res;
+            let data: any = resData?.data ?? null;
+            proxyData.width = data.width;
+            proxyData.height = data.height;
+            proxyData.spaceList = data.spaceList;
+            proxyData.setSpaceColor();
+            proxyData.initCanvas();
+          })
+          .catch(() => {});
+      },
+      // 格式化地图数据
+      formatePage() {
+        let spaceList: any = [
+          {
+            localName: "空间1",
+            spaceId: "1",
+            canClick: true,
+            deviceArr: [
+              { left: 1346.8, top: 1281.975 },
+              { left: 1326.35, top: 1282.4 },
+              { left: 1304.875, top: 1282.6 },
+            ],
+            logoArr: [
+              { left: 1286.9, top: 1228.5 },
+              { left: 1287.1, top: 1239.025 },
+            ],
+            pointArr: [
+              { left: 1369.626, top: 1178.549 },
+              { left: 1329.594, top: 1178.549 },
+              { left: 1294.238, top: 1143.194 },
+              { left: 1179.453, top: 1257.98 },
+              { left: 1205.969, top: 1284.496 },
+              { left: 1202.218, top: 1288.248 },
+              { left: 1202.218, top: 1296.049 },
+              { left: 1369.626, top: 1296.049 },
+            ],
+          },
+        ];
+        spaceList.map((item: any) => {
+          item.deviceArr.map((dev: any) => {
+            dev.top = proxyData.height - dev.top;
+          });
+          item.logoArr.map((dev: any) => {
+            dev.top = proxyData.height - dev.top;
+          });
+          item.pointArr.map((dev: any) => {
+            dev.top = proxyData.height - dev.top;
+          });
+        });
+        proxyData.spaceList = spaceList;
+      },
+    });
+    nextTick(() => {
+      proxyData.bindEvent();
+    });
+    onMounted(() => {
+      // proxyData.getMapInfo();
+      proxyData.formatePage();
+      proxyData.initCanvas();
+    });
+    return {
+      ...toRefs(proxyData),
+    };
+  },
+});
+</script>
+  <style lang="scss" scoped>
+.canvasDom {
+  position: relative;
+}
+</style>
+