vue若依集成C#的singalR接收实时数据
要写一个实时监控页面,监控堆垛机实时状态以及线体上是否有载具、是否有任务、是否有告警。项目是若依前端,后端是Java接口。要跳过Java接口,直接对接C#的signalR推送数据。需要配置两个总接口地址,原先的Java总接口地址不能删。这里的signalR是Microsoft的sigalR,开始还搞错了,搞成了另一种signalR的.netCore的版本,package.json依赖包删掉,重来,重新安装Microsoft版本signalR版本。话不多说,直接上代码。
1.首先把signalR依赖包安装上
npm install @microsoft/signalr
2.配置新的C#端监控地址,在.env.development文件中添加地址
# 载具监控地址 VUE_APP_MONITRO_WCS_EQUIPMENT = 'http://XX.XXX.XX.XX:XXXXX'
在.env.production文件中添加地址,方便后面配置到nginx转发
# 载具监控地址 VUE_APP_MONITRO_WCS_EQUIPMENT = '/monitro-api'
3.index.vue监控页面引入signalR
import * as signalR from "@microsoft/signalr";
3.1在assets/js目录下创建eventBus.js文件,文件内容如下:
import Vue from 'vue'; export default new Vue();
4.连接signalR接收数据,在index.vue中methods: {}写入connect()方法
//接收wcs线体和堆垛机数据 connect() { let url = `${process.env.VUE_APP_MONITRO_WCS_EQUIPMENT}/Equipment`; //本地开发版 singalR地址先写死 后期需要后端配置到nginx中 // let url = `http://XX.XXX.XX.XX:XXXXX/Equipment`; // let token = store.getters.token.replace("Bearer ", ""); let token; const builder = new signalR.HubConnectionBuilder(); this.connection = builder .withUrl(url, { accessTokenFactory: () => token, }) .withAutomaticReconnect({ nextRetryDelayInMilliseconds: () => 60000, }) //断线重连 .build(); // 接收信息成功 线体 this.connection.on("ReceiveMessage", (message) => { // console.log(message, "接收线体信息成功"); //通过总线发送输送线实时任务 bus.$emit("sendTransmissionLineByBus", message); if (message && message.length > 0) { //拼接接收到底所有线体集合 for (let i = 0; i < message.length; i++) { this.conveyorUnitDtos = this.conveyorUnitDtos.concat( message[i].conveyorUnitDtos ); } //删除所有线体集合arr中的重复对象 var newArr = []; var arrId = []; for (var item of this.conveyorUnitDtos) { if (arrId.indexOf(item["id"]) == -1) { arrId.push(item["id"]); newArr.push(item); } } this.conveyorUnitDtos = newArr; if (this.conveyorUnitDtos.length > 0) { //线体告警数组 var conveyorErrorArr = []; //线体告警隐藏位数组 var conveyorErrorHiddenArr = []; //线体载具数组 var conveyorGoodsArr = []; //线体载具隐藏位数组 var conveyorGoodsHiddenArr = []; //线体载具任务数组 var conveyorTaskNumArr = []; //线体载具任务编号ID数组 var conveyorTaskNumIdArr = []; //线体载具任务隐藏位数组 var conveyorTaskNumHiddenArr = []; this.conveyorUnitDtos.map((cObj, index) => { //conveyorGoods 1=无货、2=有货 //conveyorTaskNum 任务号 //conveyorError 0=无报警 其他=报警 if (cObj.conveyorGoods == 2) { conveyorGoodsArr.push(cObj.id); } else { conveyorGoodsArr = conveyorGoodsArr.filter( (item) => item != cObj.id ); } // 任务号 if (cObj.conveyorTaskNum != 0) { let cob = { id: cObj.id, conveyorTaskNum: cObj.conveyorTaskNum, }; conveyorTaskNumArr.push(cob); conveyorTaskNumIdArr.push(cObj.id); } else { // let cob = { id: cObj.id, conveyorTaskNum: cObj.conveyorTaskNum, }; //conveyorTaskNum等于0 已完成的任务 需要清空之前的任务数组值 conveyorTaskNumArr = conveyorTaskNumArr.filter( (val) => val.id !== cObj.id ); conveyorTaskNumIdArr = conveyorTaskNumIdArr.filter( (item) => item != cObj.id ); } //告警 if (cObj.conveyorError != 0) { conveyorErrorArr.push(cObj.id); } else { //已清除的告警 需要从之前的告警数组值清除 conveyorErrorArr = conveyorErrorArr.filter( (item) => item != cObj.id ); } }); //隐藏的线体载具 conveyorGoodsHiddenArr = line_vehicle_Change(conveyorGoodsArr); //隐藏的线体告警 conveyorErrorHiddenArr = line_error_Change(conveyorErrorArr); //隐藏的线体任务号 conveyorTaskNumHiddenArr = line_taskNum_Change(conveyorTaskNumIdArr); //显示的线体载具和线体任务号 for (let i = 0; i < conveyorGoodsArr.length; i++) { this.xtVehicle_arr[`xtVehicle_` + conveyorGoodsArr[i]] = xtVehicleGreen; } //隐藏的线体载具和线体任务号 for (let i = 0; i < conveyorGoodsHiddenArr.length; i++) { this.xtVehicle_arr[`xtVehicle_` + conveyorGoodsHiddenArr[i]] = ""; } //数组新增一条记录删除一条记录会更新dom this.xtVehicle_arr.push("xtVehicle"); this.xtVehicle_arr.pop(); //显示的线体任务号 for (let i = 0; i < conveyorTaskNumArr.length; i++) { this.xtVehicle_task_arr[ `xtVehicle_` + conveyorTaskNumArr[i].id + `_task` ] = conveyorTaskNumArr[i].conveyorTaskNum; } //隐藏的线体任务号 for (let i = 0; i < conveyorTaskNumHiddenArr.length; i++) { this.xtVehicle_task_arr[ `xtVehicle_` + conveyorTaskNumHiddenArr[i].id + `_task` ] = ""; } //数组新增一条记录删除一条记录会更新dom this.xtVehicle_task_arr.push("xtVehicle_task"); this.xtVehicle_task_arr.pop(); //显示的线体告警 for (let i = 0; i < conveyorErrorArr.length; i++) { this.xtAlarm_arr[`xtAlarm_` + conveyorErrorArr[i]] = xtAlarmRed; } //隐藏的线体告警 for (let i = 0; i < conveyorErrorHiddenArr.length; i++) { this.xtAlarm_arr[`xtAlarm_` + conveyorErrorHiddenArr[i]] = ""; } //数组新增一条记录删除一条记录会更新dom this.xtAlarm_arr.push("xtAlarm"); this.xtAlarm_arr.pop(); } } }); // 接收信息成功 堆垛机 this.connection.on("ReceiveStackerStk", (message) => { // console.log(message, "接收堆垛机信息成功"); //通过总线发送堆垛机实时数据 bus.$emit("sendPilerByBus", message); if (message && message.length > 0) { //1#堆垛机 2#堆垛机 3#堆垛机 4#堆垛机 var num1ddjObj; var num2ddjObj; var num3ddjObj; var num4ddjObj; //1#虫卵库隐藏的列数 var num1ddjObjForkHiddenColumn = []; //2#幼虫库隐藏的列数 var num2ddjObjForkHiddenColumn = []; //3#成虫库隐藏的列数 var num3ddjObjForkHiddenColumn = []; //4#成虫库隐藏的列数 var num4ddjObjForkHiddenColumn = []; message.map((dObj, index) => { //1#堆垛机 if (dObj.tunnelId == 1) { num1ddjObj = dObj; if (num1ddjObj) { //显示当前列 frontForkColumn if (num1ddjObj.frontForkColumn != 0) { this.yx_1hddj_arr[`yx_1hddj_` + num1ddjObj.frontForkColumn] = ddjGreen; } else { this.yx_1hddj_arr[yx_1hddj_2] = ddjGreen; } var element = num1ddjObj.frontForkColumn; //隐藏的1#虫卵库 列 num1ddjObjForkHiddenColumn = piler_1_Change(element); //隐藏的1#虫卵库 列 for (let i = 0; i < num1ddjObjForkHiddenColumn.length; i++) { this.yx_1hddj_arr[ `yx_1hddj_` + num1ddjObjForkHiddenColumn[i] ] = ""; } //显示任务号 //任务是什么动作 firstType // 1 -入 (入库) ;2 -出 (出库);3 -移 (移库任务) 4 -输送线用(目前堆垛机用不到); // 5 -转运(直出 移动 堆垛机 从头走到尾部) 0-无任务 //单工位同时最多有一个任务号 双工位同时最多有两个任务号 //堆垛机类型(1-虫卵库双工位 0-单工位 幼虫库成虫库单工位) //前插(单工位)frontTaskDto.wcsId -任务号 //后插(双工位)backTaskDto.wcsId -任务号 //任务号 任务类型+任务号组成 var taskNumberStr; //前插 var froTaskDto; //后插 var baTaskDto; if (num1ddjObj.platform == 1) { froTaskDto = num1ddjObj.frontTaskDto; baTaskDto = num1ddjObj.backTaskDto; taskNumberStr = (froTaskDto.firstType == 1 ? "入:" : froTaskDto.firstType == 2 ? "出:" : froTaskDto.firstType == 3 ? "移:" : froTaskDto.firstType == 4 ? "输送线用:" : froTaskDto.firstType == 5 ? "转运:" : "") + froTaskDto.wcsId; taskNumberStr = taskNumberStr + (baTaskDto.firstType == 1 ? "入:" : baTaskDto.firstType == 2 ? "出:" : baTaskDto.firstType == 3 ? "移:" : baTaskDto.firstType == 4 ? "输送线用:" : baTaskDto.firstType == 5 ? "转运:" : "") + baTaskDto.wcsId; } else { froTaskDto = num1ddjObj.frontTaskDto; taskNumberStr = (froTaskDto.firstType == 1 ? "入:" : froTaskDto.firstType == 2 ? "出:" : froTaskDto.firstType == 3 ? "移:" : froTaskDto.firstType == 4 ? "输送线用:" : froTaskDto.firstType == 5 ? "转运:" : "") + froTaskDto.wcsId; } //如果堆垛机有当前列 任务号显示在对应当前列位置上 没有当前列 就显示在堆垛机首个位置 if (num1ddjObj.frontForkColumn != 0) { this.yx_1hddj_arr[ `yx_1hddj_` + num1ddjObj.frontForkColumn + `_task` ] = taskNumberStr; } else { this.yx_1hddj_arr[`yx_1hddj_` + 2 + `_task`] = taskNumberStr; } //隐藏的1#虫卵库 其他任务号 for (let i = 0; i < num1ddjObjForkHiddenColumn.length; i++) { this.yx_1hddj_arr[ `yx_1hddj_` + num1ddjObjForkHiddenColumn[i] + `_task` ] = ""; } } //数组新增一条记录删除一条记录会更新dom this.yx_1hddj_arr.push("1#"); this.yx_1hddj_arr.pop(); } //2#堆垛机 if (dObj.tunnelId == 2) { num2ddjObj = dObj; if (num2ddjObj) { //显示当前列 frontForkColumn if (num2ddjObj.frontForkColumn != 0) { this.yx_2hddj_arr[`yx_2hddj_` + num2ddjObj.frontForkColumn] = ddjGreen; } else { this.yx_2hddj_arr[yx_1hddj_1] = ddjGreen; } var element = num2ddjObj.frontForkColumn; //隐藏的2#虫卵库 列 num2ddjObjForkHiddenColumn = piler_2_Change(element); //隐藏的2#虫卵库 列 for (let i = 0; i < num2ddjObjForkHiddenColumn.length; i++) { this.yx_2hddj_arr[ `yx_2hddj_` + num2ddjObjForkHiddenColumn[i] ] = ""; } //任务号 任务类型+任务号组成 var taskNumberStr; //前插 var froTaskDto; //后插 var baTaskDto; if (num2ddjObj.platform == 1) { froTaskDto = num2ddjObj.frontTaskDto; baTaskDto = num2ddjObj.backTaskDto; taskNumberStr = (froTaskDto.firstType == 1 ? "入:" : froTaskDto.firstType == 2 ? "出:" : froTaskDto.firstType == 3 ? "移:" : froTaskDto.firstType == 4 ? "输送线用:" : froTaskDto.firstType == 5 ? "转运:" : "") + froTaskDto.wcsId; taskNumberStr = taskNumberStr + (baTaskDto.firstType == 1 ? "入:" : baTaskDto.firstType == 2 ? "出:" : baTaskDto.firstType == 3 ? "移:" : baTaskDto.firstType == 4 ? "输送线用:" : baTaskDto.firstType == 5 ? "转运:" : "") + baTaskDto.wcsId; } else { froTaskDto = num2ddjObj.frontTaskDto; taskNumberStr = (froTaskDto.firstType == 1 ? "入:" : froTaskDto.firstType == 2 ? "出:" : froTaskDto.firstType == 3 ? "移:" : froTaskDto.firstType == 4 ? "输送线用:" : froTaskDto.firstType == 5 ? "转运:" : "") + froTaskDto.wcsId; } //如果堆垛机有当前列 任务号显示在对应当前列位置上 没有当前列 就显示在堆垛机首个位置 if (num2ddjObj.frontForkColumn != 0) { this.yx_2hddj_arr[ `yx_2hddj_` + num2ddjObj.frontForkColumn + `_task` ] = taskNumberStr; } else { this.yx_2hddj_arr[`yx_2hddj_` + 1 + `_task`] = taskNumberStr; } //隐藏的2#幼虫库 其他任务号 for (let i = 0; i < num2ddjObjForkHiddenColumn.length; i++) { this.yx_2hddj_arr[ `yx_2hddj_` + num2ddjObjForkHiddenColumn[i] + `_task` ] = ""; } } //数组新增一条记录删除一条记录会更新dom this.yx_2hddj_arr.push("2#"); this.yx_2hddj_arr.pop(); } //3#堆垛机 if (dObj.tunnelId == 3) { num3ddjObj = dObj; if (num3ddjObj) { //显示当前列 frontForkColumn if (num3ddjObj.frontForkColumn != 0) { this.yx_3hddj_arr[`yx_3hddj_` + num3ddjObj.frontForkColumn] = ddjGreen; } else { this.yx_3hddj_arr[yx_3hddj_1] = ddjGreen; } var element = num3ddjObj.frontForkColumn; //隐藏的3#虫卵库 列 num3ddjObjForkHiddenColumn = piler_3_Change(element); //隐藏的3#虫卵库 列 for (let i = 0; i < num3ddjObjForkHiddenColumn.length; i++) { this.yx_3hddj_arr[ `yx_3hddj_` + num3ddjObjForkHiddenColumn[i] ] = ""; } //任务号 任务类型+任务号组成 var taskNumberStr; //前插 var froTaskDto; //后插 var baTaskDto; if (num3ddjObj.platform == 1) { froTaskDto = num3ddjObj.frontTaskDto; baTaskDto = num3ddjObj.backTaskDto; taskNumberStr = (froTaskDto.firstType == 1 ? "入:" : froTaskDto.firstType == 2 ? "出:" : froTaskDto.firstType == 3 ? "移:" : froTaskDto.firstType == 4 ? "输送线用:" : froTaskDto.firstType == 5 ? "转运:" : "") + froTaskDto.wcsId; taskNumberStr = taskNumberStr + (baTaskDto.firstType == 1 ? "入:" : baTaskDto.firstType == 2 ? "出:" : baTaskDto.firstType == 3 ? "移:" : baTaskDto.firstType == 4 ? "输送线用:" : baTaskDto.firstType == 5 ? "转运:" : "") + baTaskDto.wcsId; } else { froTaskDto = num3ddjObj.frontTaskDto; taskNumberStr = (froTaskDto.firstType == 1 ? "入:" : froTaskDto.firstType == 2 ? "出:" : froTaskDto.firstType == 3 ? "移:" : froTaskDto.firstType == 4 ? "输送线用:" : froTaskDto.firstType == 5 ? "转运:" : "") + froTaskDto.wcsId; } //如果堆垛机有当前列 任务号显示在对应当前列位置上 没有当前列 就显示在堆垛机首个位置 if (num3ddjObj.frontForkColumn != 0) { this.yx_3hddj_arr[ `yx_3hddj_` + num3ddjObj.frontForkColumn + `_task` ] = taskNumberStr; } else { this.yx_3hddj_arr[`yx_3hddj_` + 1 + `_task`] = taskNumberStr; } //隐藏的3#成虫库 其他任务号 for (let i = 0; i < num3ddjObjForkHiddenColumn.length; i++) { this.yx_3hddj_arr[ `yx_3hddj_` + num3ddjObjForkHiddenColumn[i] + `_task` ] = ""; } } //数组新增一条记录删除一条记录会更新dom this.yx_3hddj_arr.push("3#"); this.yx_3hddj_arr.pop(); } //4#堆垛机 if (dObj.tunnelId == 4) { num4ddjObj = dObj; if (num4ddjObj) { //显示当前列 frontForkColumn if (num4ddjObj.frontForkColumn != 0) { this.yx_4hddj_arr[`yx_4hddj_` + num4ddjObj.frontForkColumn] = ddjGreen; } else { this.yx_4hddj_arr[yx_4hddj_1] = ddjGreen; } //数组新增一条记录删除一条记录会更新dom this.yx_4hddj_arr.push("4#"); this.yx_4hddj_arr.pop(); var element = num4ddjObj.frontForkColumn; //TODO //隐藏的4#虫卵库 列 num4ddjObjForkHiddenColumn = piler_4_Change(element); //隐藏的4#虫卵库 列 for (let i = 0; i < num4ddjObjForkHiddenColumn.length; i++) { this.yx_4hddj_arr[ `yx_4hddj_` + num4ddjObjForkHiddenColumn[i] ] = ""; } //任务号 任务类型+任务号组成 var taskNumberStr; //前插 var froTaskDto; //后插 var baTaskDto; if (num4ddjObj.platform == 1) { froTaskDto = num4ddjObj.frontTaskDto; baTaskDto = num4ddjObj.backTaskDto; taskNumberStr = (froTaskDto.firstType == 1 ? "入:" : froTaskDto.firstType == 2 ? "出:" : froTaskDto.firstType == 3 ? "移:" : froTaskDto.firstType == 4 ? "输送线用:" : froTaskDto.firstType == 5 ? "转运:" : "") + froTaskDto.wcsId; taskNumberStr = taskNumberStr + (baTaskDto.firstType == 1 ? "入:" : baTaskDto.firstType == 2 ? "出:" : baTaskDto.firstType == 3 ? "移:" : baTaskDto.firstType == 4 ? "输送线用:" : baTaskDto.firstType == 5 ? "转运:" : "") + baTaskDto.wcsId; } else { froTaskDto = num4ddjObj.frontTaskDto; taskNumberStr = (froTaskDto.firstType == 1 ? "入:" : froTaskDto.firstType == 2 ? "出:" : froTaskDto.firstType == 3 ? "移:" : froTaskDto.firstType == 4 ? "输送线用:" : froTaskDto.firstType == 5 ? "转运:" : "") + froTaskDto.wcsId; } //如果堆垛机有当前列 任务号显示在对应当前列位置上 没有当前列 就显示在堆垛机首个位置 if (num4ddjObj.frontForkColumn != 0) { this.yx_4hddj_arr[ `yx_4hddj_` + num4ddjObj.frontForkColumn + `_task` ] = taskNumberStr; } else { this.yx_4hddj_arr[yx_4hddj_1_task] = taskNumberStr; } //隐藏的4#成虫库 其他任务号 for (let i = 0; i < num4ddjObjForkHiddenColumn.length; i++) { this.yx_4hddj_arr[ `yx_4hddj_` + num4ddjObjForkHiddenColumn[i] + `_task` ] = ""; } } //数组新增一条记录删除一条记录会更新dom this.yx_4hddj_arr.push("4#"); this.yx_4hddj_arr.pop(); } }); } }); //自动重连成功后的处理 this.connection.onreconnected((connectionId) => { console.log(connectionId, "自动重新连接成功"); }); // 监听关闭 this.connection.onclose((res) => { console.log("监听关闭", res); }); // 开始连接 this.connection .start() .then((res) => { // console.log("启动即时通信成功", res); }) .catch((err) => { console.log(err); }); },
5.index.vue中 mounted() 方法内初始化1号堆垛机数组、2号堆垛机数组、3号堆垛机数组、4号堆垛机数组、告警数组、载具数组、载具任务数组数据名称以及数据内容。
mounted() { this.initPanZoom(); this.yx_1hddj_arr = []; this.yx_2hddj_arr = []; this.yx_3hddj_arr = []; this.yx_4hddj_arr = []; this.xtAlarm_arr = []; this.xtVehicle_arr = []; this.xtVehicle_task_arr = []; //初始化1#堆垛机 堆垛机列数组 任务数组 从3号位开始 到43号位结束 总共41个列位置(2号位为初始0位) for (let i = 2; i <= 43; i++) { if (i == 2) { this.yx_1hddj_arr[`yx_1hddj_` + i] = ddjGreen; this.yx_1hddj_arr[`yx_1hddj_` + i + `_task`] = "出:0"; } else { this.yx_1hddj_arr[`yx_1hddj_` + i] = ""; this.yx_1hddj_arr[`yx_1hddj_` + i + `_task`] = ""; } } //初始化2#堆垛机 堆垛机列数组 任务数组 从2号位开始 到29号位结束 总共28个列位置(1号位为初始0位) for (let i = 1; i <= 29; i++) { if (i == 1) { this.yx_2hddj_arr[`yx_2hddj_` + i] = ddjGreen; this.yx_2hddj_arr[`yx_2hddj_` + i + `_task`] = "出:0"; } else { this.yx_2hddj_arr[`yx_2hddj_` + i] = ""; this.yx_2hddj_arr[`yx_2hddj_` + i + `_task`] = ""; } } //初始化3#堆垛机 堆垛机列数组 任务数组 从2号位开始 到29号位结束 总共28个列位置(1号位为初始0位) for (let i = 1; i <= 29; i++) { if (i == 1) { this.yx_3hddj_arr[`yx_3hddj_` + i] = ddjGreen; this.yx_3hddj_arr[`yx_3hddj_` + i + `_task`] = "出:0"; } else { this.yx_3hddj_arr[`yx_3hddj_` + i] = ""; this.yx_3hddj_arr[`yx_3hddj_` + i + `_task`] = ""; } } //初始化4#堆垛机 堆垛机列数组 任务数组 从2号位开始 到29号位结束 总共28个列位置 (1号位是初始0位) for (let i = 1; i <= 29; i++) { if (i == 1) { this.yx_4hddj_arr[`yx_4hddj_` + i] = ddjGreen; this.yx_4hddj_arr[`yx_4hddj_` + i + `_task`] = "出:0"; } else { this.yx_4hddj_arr[`yx_4hddj_` + i] = ""; this.yx_4hddj_arr[`yx_4hddj_` + i + `_task`] = ""; } } //初始化线体载具 线体任务 线体告警 // 1#虫卵库线体编号1001~1017 2#幼虫库线体编号1018~1040 (生成的线体编号数组中间有个别用不到的线体编号可以忽略) // 3#成虫库 4#成虫库 线体编号2001~2067 for (let i = 1001; i <= 1040; i++) { this.xtVehicle_arr[`xtVehicle_` + i] = ""; this.xtVehicle_task_arr[`xtVehicle_` + i + `_task`] = ""; this.xtAlarm_arr[`xtAlarm_` + i] = ""; } for (let i = 2001; i <= 2067; i++) { this.xtVehicle_arr[`xtVehicle_` + i] = ""; this.xtVehicle_task_arr[`xtVehicle_` + i + `_task`] = ""; this.xtAlarm_arr[`xtAlarm_` + i] = ""; } },
6.在<script></script>标签内引入图片
//堆垛机 红 //料箱 笼框 载具 //告警 //堆垛机 绿 import ddjRed from "@/assets/images/svg/堆垛机02_红.png"; import ddjGreen from "@/assets/images/svg/堆垛机02_横向_绿.png"; import xtAlarmRed from "@/assets/images/svg/g告警数据.png"; import xtVehicleGreen from "@/assets/images/svg/linforma_料箱_绿 (2).png";
7.index.vue中引入了svg静态堆垛机和线体图,svg图可以拖拽无限放大缩小, 这里可以参考另我的一篇文章《svg可拖拽无限放大缩小》,感兴趣的可以移步到文章链接:https://www.cnblogs.com/chenyangjava/p/18336511 查看详情,这里不做展开描述。
<template> <div class="allbgc"> <div class="contentwid"> <!-- // 需要拖动的dom --> <div ref="dom" @wheel="wheel"> <div class="svgdiv"> <svg id="vehicleMonitorId" ref="mysvg" data-name="vehicleMonitorName" xmlns="http://www.w3.org/2000/svg" :viewBox="viewboxw"> <!-- <title>二楼上层</title> --> <g> <ellipse class="st0" cx="39.2" cy="106" rx="28.5" ry="32" /> <g> <g> <g> <g> <g> <text transform="matrix(1.2 0 0 1 18.1001 119.2002)" class="st1 st2 st3"> 1# </text> </g> </g> </g> </g> </g> </g> <!-- todo --> <!-- 引入4号堆垛机货架 最后10列 19~28列 svg --> <!-- <DdjHj /> --> <!-- <g id="svgElement" ></g> --> <rect x="81.2" y="889.5" class="st4" width="608.7" height="60.7" /> <rect x="81.1" y="890" class="st5" width="60.1" height="60.3" /> <line class="st6" x1="81.1" y1="950.3" x2="141.2" y2="890" /> <line class="st6" x1="81.1" y1="890" x2="141.2" y2="950.3" /> <rect x="142" y="890" class="st5" width="60.1" height="60.3" /> <line class="st6" x1="142" y1="950.3" x2="202.1" y2="890" /> <line class="st6" x1="142" y1="890" x2="202.1" y2="950.3" /> <rect x="202.9" y="890" class="st5" width="60.1" height="60.3" /> <line class="st6" x1="202.9" y1="950.3" x2="263" y2="890" />
</svg>
<clipPath id="clippath"> <rect class="cls-3" x="1729.9" y="837.4" width="45.7" height="35.9" /> </clipPath> </div> </div> </div>
8.数据刷刷的出来了,上图。
9.补充:上图svg图可以无限放大缩小,图上有600、700个数据点,随意拖拽不卡顿。查看详情看笔者另一篇文章《svg可拖拽无限放大缩小》 ,文章链接:https://www.cnblogs.com/chenyangjava/p/18336511