|
@@ -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>
|
|
|
+
|