js 绘制2D机柜(二)2D机柜的进阶绘制

2023-11-22 19:21
文章标签 进阶 js 绘制 2d 机柜

本文主要是介绍js 绘制2D机柜(二)2D机柜的进阶绘制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上一篇写了基础的2D机柜绘制,今天这篇记录下机柜绘制的进阶篇。本篇主要是就数据封装及机柜界面的优化。

首先是数据封装,正常来说数据的封装不会如上篇那么简单,这里加入更详细的数据用于展示信息,所需封装的数据如下:

    //configuration          机柜配置信息//cabinet_id             机柜id//u_number               设备所占u信息 格式为 (所占单元起始u-总共占单元数)//positive_or_negative   表示正反机柜//left_or_right          设备在单元左右 0为左1为右 不可为null或空 若单元仅一台设备则为0//device_number          设备编号//device_category        设备品类//device_brand           设备品牌//device_type            设备类型//device_id              设备idfunction sample() {var array = new Array();array.push({configuration: '机柜配置信息1', cabinet_id: '1', u_number: '1-21', positive_or_negative: 1, left_or_right: 0, device_number: '设备编号1', device_category: '设备品类1', device_brand:'设备品牌1', device_type: '设备型号1', device_typeId:6, device_id:1});array.push({configuration: '机柜配置信息2', cabinet_id: '2', u_number: '1-21', positive_or_negative: 1, left_or_right: 1, device_number: '设备编号2', device_category: '设备品类2', device_brand:'设备品牌2', device_type: '设备型号2', device_typeId:6, device_id:2});array.push({configuration: '机柜配置信息3', cabinet_id: '3', u_number: '24-3', positive_or_negative: 1, left_or_right: 0, device_number: '设备编号3', device_category: '设备品类3', device_brand:'设备品牌3', device_type: '设备型号3', device_typeId:2, device_id:3});array.push({configuration: '机柜配置信息4', cabinet_id: '4', u_number: '33-3', positive_or_negative: 1, left_or_right: 0, device_number: '设备编号4', device_category: '设备品类4', device_brand:'设备品牌4', device_type: '设备型号4', device_typeId:3, device_id:4});initCabinet(30, array, 'positiveCabinet');initCabinet(30, array, 'negativeCabinet');}

因为我们这个项目当前后台尚未完成,因此这里所展示的字段都是直接从数据库中简单查出来的,这样能够大大简化后台的封装操作同时减少其他开发人员使用本功能时候的使用难度。

调用的方法和第一篇的差不多,只是这里引入了同一单元左右设备的概念。方法改造如下:

    for (var i = 0; i < unitArray.length; i++) {var arrayElement = unitArray[i];//array中的元素var indexAndLength = arrayElement.u_number.split('-');//设备所占机柜的起始单元及单元总数var mapKey = indexAndLength[0];//封装设备至map中key为设备起始单元indexvar mapElement = map[mapKey];//获取map中的元素if (typeof(mapElement) == 'undefined') {//起始单元没有数据mapElement = {};map[mapKey] = mapElement;initMap(mapElement);}var deviceIndex = arrayElement.left_or_right == '1' ? 1 : 0; //指定数据添加的indexmapElement.content[deviceIndex] = arrayElement.configuration + "," + arrayElement.device_number + "," + arrayElement.device_category + "," + arrayElement.device_brand + "," + arrayElement.device_type;mapElement.length[deviceIndex] = indexAndLength[1];mapElement.type[deviceIndex] = arrayElement.device_typeId;mapElement.cabinetId[deviceIndex] = arrayElement.cabinet_id;mapElement.deviceId[deviceIndex] = arrayElement.device_id;mapElement.elementCount += 1;}

这里数据的封装较上篇来说,最大的不同就是存入map的value由原来的单一数值变成了数组,用以处理同单元存在两个设备的情况。下面贴上初始化map元素的方法:

//初始化map
function initMap(map) {var contentList = new Array(); contentList.push('-1', '-1');//设备内容var lengthList = new Array(); lengthList.push('-1', '-1');//设备所占单元数var typeList = new Array(); typeList.push('-1', '-1');//设备类型,用于决定图片var cabinetIdList = new Array(); typeList.push('-1', '-1');var deviceIdList = new Array(); typeList.push('-1', '-1');map.content = contentList;map.length = lengthList;map.type = typeList;map.cabinetId = cabinetIdList;map.deviceId = deviceIdList;map.elementCount = 0;//初始化单元设备数量
}

注意这里封装好的map的key不是最终的key因为存在同单元多个设备的情况,因此我们需要在数据初步封装完成后再次循环map确认每组设备实际所占的单元个数。

    var mapFinal = {};for (var key in map) {var mapEl = map[key];//获取map元素var elCount = mapEl.elementCount;var mapIndex = -1;//最终map的indexif (elCount == 1) {mapIndex = parseInt(key) + parseInt(mapEl.length[0]) - 1;}else{mapIndex = parseInt(key) + (parseInt(mapEl.length[0]) < parseInt(mapEl.length[1]) ? parseInt(mapEl.length[1]) : parseInt(mapEl.length[0])) - 1;}mapFinal[mapIndex] = mapEl;}

封装好数据之后循环unit总数如上篇一样处理即可:

    for (var i = unitCount; i >= 1; i--) {if (typeof(mapFinal[i]) == 'undefined') {content += '<div class="areaBlock" align="center" data-geo=""><div class="blockFont">' + i + '</div></div>'} else {var deviceCount = mapFinal[i].elementCount;if (deviceCount == '1'){var length = parseInt(mapFinal[i].length[0]);var type = mapFinal[i].type[0];var height = blockHeight * (length) + blockInterval * (length - 1) + 'px';var deviceContent = mapFinal[i].content[0];var cabinetId = mapFinal[i].cabinetId[0];var deviceId = mapFinal[i].deviceId[0];i -= (length - 1);content += '<div class="areaBlockWithImg" align="center" style="height: ' + height + ';background-image: url('+ initImg(type) +')" data-geo="" onclick="deviceOnclick(' + cabinetId + ',' + deviceId + ')">' + '<input id="content" type="hidden" value="' + deviceContent+'">' + '</div>'}else{var lengthLeft = parseInt(mapFinal[i].length[0]);//左边设备所占单元数var typeLeft = mapFinal[i].type[0];//左边设备类型var deviceContentLeft = mapFinal[i].content[0];//左边设备信息var cabinetIdLeft = mapFinal[i].cabinetId[0];var deviceIdLeft = mapFinal[i].deviceId[0];var lengthRight = parseInt(mapFinal[i].length[1]);//右边设备所占单元数var typeRight = mapFinal[i].type[1];//右边设备类型var deviceContentRight = mapFinal[i].content[1];//右边设备信息var cabinetIdRight = mapFinal[i].cabinetId[1];var deviceIdRight = mapFinal[i].deviceId[1];var length = lengthLeft > lengthRight ? lengthLeft : lengthRight;//取两个设备所占单元最大数var height = blockHeight * (length) + blockInterval * (length - 1) + 'px';//指定高度i -= (length - 1);content += '<div class="areaBlock" style="height: '+ height +'">';content += '<div class="areaBlockWithDoubleDeviceLeft" style="background-image: url('+ initImg(typeLeft) +')" data-geo="" onclick="deviceOnclick(' + cabinetIdLeft + ',' + deviceIdLeft + ')">' + '<input id="content" type="hidden" value="' + deviceContentLeft +'">' + '</div>';content += '<div class="areaMiddleBlock"></div>'content += '<div class="areaBlockWithDoubleDeviceRight" style="background-image: url('+ initImg(typeRight) +')" data-geo="" onclick="deviceOnclick(' + cabinetIdRight + ',' + deviceIdRight + ')">' + '<input id="content" type="hidden" value="' + deviceContentRight +'">' + '</div>';content += '</div>';}}}

这里再做一个显示方面的优化,正常一个设备tooltip是显示在右侧,如果有两个设备并且都显示在右侧那么就显得不友好,因此这里也设置两种不同的tooltip用于不同位置的设备:

//初始化tooltip
function initTooltip(unitCount) {var leftPositionOffset = 'right-'+ (32+Math.abs(parseInt(unitCount)-40)/2*3)+' center';$('.areaBlockWithDoubleDeviceLeft').tooltip({position: {my: leftPositionOffset, at: "left center"},items: "[data-geo]",content: function () {var element = $(this);var deviceContent = '';if (typeof(this.getElementsByTagName('input')[0]) != 'undefined') {deviceContent = this.getElementsByTagName('input')[0].value;}if (element.is("[data-geo]")) {var text = deviceContent == ''? element.text().split(',') : deviceContent.split(',');return showInfo(text);}}});$('.areaBlockWithDoubleDeviceRight, .areaBlock, .areaBlockWithImg').tooltip({position: {my: "left+50 center", at: "right center"},items: "[data-geo]",content: function () {var element = $(this);var deviceContent = '';if (typeof(this.getElementsByTagName('input')[0]) != 'undefined') {deviceContent = this.getElementsByTagName('input')[0].value;}if (element.is("[data-geo]")) {var text = deviceContent == ''? element.text().split(',') : deviceContent.split(',');return showInfo(text);}}});
}

这样一来最终的效果图如下:

 

这里贴下完整的js代码:

//map元素字段说明
//content 单元设备信息 list
//length 单元设备所占单元数 list
//type 单元设备类别 list
//elementCount 单元设备数量 int 若数量为1则处理所有数组第一个元素
function initCabinet(unitCount, unitArray, cabinetBlockId) {var blockInterval = 3;//单元的间隔var blockHeight = 12;//单元高度var map = {};for (var i = 0; i < unitArray.length; i++) {var arrayElement = unitArray[i];//array中的元素var indexAndLength = arrayElement.u_number.split('-');//设备所占机柜的起始单元及单元总数var mapKey = indexAndLength[0];//封装设备至map中key为设备起始单元indexvar mapElement = map[mapKey];//获取map中的元素if (typeof(mapElement) == 'undefined') {//起始单元没有数据mapElement = {};map[mapKey] = mapElement;initMap(mapElement);}var deviceIndex = arrayElement.left_or_right == '1' ? 1 : 0; //指定数据添加的indexmapElement.content[deviceIndex] = arrayElement.configuration + "," + arrayElement.device_number + "," + arrayElement.device_category + "," + arrayElement.device_brand + "," + arrayElement.device_type;mapElement.length[deviceIndex] = indexAndLength[1];mapElement.type[deviceIndex] = arrayElement.device_typeId;mapElement.cabinetId[deviceIndex] = arrayElement.cabinet_id;mapElement.deviceId[deviceIndex] = arrayElement.device_id;mapElement.elementCount += 1;}var mapFinal = {};for (var key in map) {var mapEl = map[key];//获取map元素var elCount = mapEl.elementCount;var mapIndex = -1;//最终map的indexif (elCount == 1) {mapIndex = parseInt(key) + parseInt(mapEl.length[0]) - 1;}else{mapIndex = parseInt(key) + (parseInt(mapEl.length[0]) < parseInt(mapEl.length[1]) ? parseInt(mapEl.length[1]) : parseInt(mapEl.length[0])) - 1;}mapFinal[mapIndex] = mapEl;}var parentBlockHeight = (blockHeight + blockInterval) * unitCount + 'px';$('.parentBlock').css('height', parentBlockHeight);var content = "";for (var i = unitCount; i >= 1; i--) {if (typeof(mapFinal[i]) == 'undefined') {content += '<div class="areaBlock" align="center" data-geo=""><div class="blockFont">' + i + '</div></div>'} else {var deviceCount = mapFinal[i].elementCount;if (deviceCount == '1'){var length = parseInt(mapFinal[i].length[0]);var type = mapFinal[i].type[0];var height = blockHeight * (length) + blockInterval * (length - 1) + 'px';var deviceContent = mapFinal[i].content[0];var cabinetId = mapFinal[i].cabinetId[0];var deviceId = mapFinal[i].deviceId[0];i -= (length - 1);content += '<div class="areaBlockWithImg" align="center" style="height: ' + height + ';background-image: url('+ initImg(type) +')" data-geo="" onclick="deviceOnclick(' + cabinetId + ',' + deviceId + ')">' + '<input id="content" type="hidden" value="' + deviceContent+'">' + '</div>'}else{var lengthLeft = parseInt(mapFinal[i].length[0]);//左边设备所占单元数var typeLeft = mapFinal[i].type[0];//左边设备类型var deviceContentLeft = mapFinal[i].content[0];//左边设备信息var cabinetIdLeft = mapFinal[i].cabinetId[0];var deviceIdLeft = mapFinal[i].deviceId[0];var lengthRight = parseInt(mapFinal[i].length[1]);//右边设备所占单元数var typeRight = mapFinal[i].type[1];//右边设备类型var deviceContentRight = mapFinal[i].content[1];//右边设备信息var cabinetIdRight = mapFinal[i].cabinetId[1];var deviceIdRight = mapFinal[i].deviceId[1];var length = lengthLeft > lengthRight ? lengthLeft : lengthRight;//取两个设备所占单元最大数var height = blockHeight * (length) + blockInterval * (length - 1) + 'px';//指定高度i -= (length - 1);content += '<div class="areaBlock" style="height: '+ height +'">';content += '<div class="areaBlockWithDoubleDeviceLeft" style="background-image: url('+ initImg(typeLeft) +')" data-geo="" onclick="deviceOnclick(' + cabinetIdLeft + ',' + deviceIdLeft + ')">' + '<input id="content" type="hidden" value="' + deviceContentLeft +'">' + '</div>';content += '<div class="areaMiddleBlock"></div>'content += '<div class="areaBlockWithDoubleDeviceRight" style="background-image: url('+ initImg(typeRight) +')" data-geo="" onclick="deviceOnclick(' + cabinetIdRight + ',' + deviceIdRight + ')">' + '<input id="content" type="hidden" value="' + deviceContentRight +'">' + '</div>';content += '</div>';}}}$('#'+cabinetBlockId).append(content);initTooltip(unitCount);
}//初始化tooltip
function initTooltip(unitCount) {var leftPositionOffset = 'right-'+ (32+Math.abs(parseInt(unitCount)-40)/2*3)+' center';leftPositionOffset = 'right-50 center';$('.areaBlockWithDoubleDeviceLeft').tooltip({position: {my: leftPositionOffset, at: "left center"},items: "[data-geo]",content: function () {var element = $(this);var deviceContent = '';if (typeof(this.getElementsByTagName('input')[0]) != 'undefined') {deviceContent = this.getElementsByTagName('input')[0].value;}if (element.is("[data-geo]")) {var text = deviceContent == ''? element.text().split(',') : deviceContent.split(',');return showInfo(text);}}});$('.areaBlockWithDoubleDeviceRight, .areaBlock, .areaBlockWithImg').tooltip({position: {my: "left+50 center", at: "right center"},items: "[data-geo]",content: function () {var element = $(this);var deviceContent = '';if (typeof(this.getElementsByTagName('input')[0]) != 'undefined') {deviceContent = this.getElementsByTagName('input')[0].value;}if (element.is("[data-geo]")) {var text = deviceContent == ''? element.text().split(',') : deviceContent.split(',');return showInfo(text);}}});
}//设备点击事件
function deviceOnclick(cabinetId, deviceId) {alert('机柜id:' + parseInt(cabinetId) + ', 设备id:' + parseInt(deviceId))
}//显示设备信息
function showInfo(text) {var content = '';if (text.length == 5) {content += "<div>" + text[1] + "</div><div>" + text[2] + "</div><div>" + text[3] + "</div>";} else {content += "<div>单元 " + text[0] + " 可使用</div>";}return content;
}//初始化设备图片
function initImg(deviceType) {var img = 'img/deviceImg/';switch (deviceType){case 1://路由器img += 'root/cisioRoot1.png';break;case 2://安全设备img += 'securityDevice/fireWall1.jpg';break;case 3://服务器img += 'server/dellServer1.jpg';break;case 4://存储设备img += 'storeDevice/storeDevice1.jpg';break;case 5://交换机img += 'swap/dellSwap1.png';break;case 6://塔式服务器img += 'towerServer/dellTowerServer1.jpg';break;default://默认img += 'defaultDevice.jpg';break;}return img;
}//初始化map
function initMap(map) {var contentList = new Array(); contentList.push('-1', '-1');//设备内容var lengthList = new Array(); lengthList.push('-1', '-1');//设备所占单元数var typeList = new Array(); typeList.push('-1', '-1');//设备类型,用于决定图片var cabinetIdList = new Array(); typeList.push('-1', '-1');var deviceIdList = new Array(); typeList.push('-1', '-1');map.content = contentList;map.length = lengthList;map.type = typeList;map.cabinetId = cabinetIdList;map.deviceId = deviceIdList;map.elementCount = 0;//初始化单元设备数量
}

这样基本上可以直接将数据库中获取的数据直接进行处理而不用后端再做更多复杂的处理。

如果后面有更复杂的需求后续还会更新。

这篇关于js 绘制2D机柜(二)2D机柜的进阶绘制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/412360

相关文章

C语言进阶(预处理命令详解)

《C语言进阶(预处理命令详解)》文章讲解了宏定义规范、头文件包含方式及条件编译应用,强调带参宏需加括号避免计算错误,头文件应声明函数原型以便主函数调用,条件编译通过宏定义控制代码编译,适用于测试与模块... 目录1.宏定义1.1不带参宏1.2带参宏2.头文件的包含2.1头文件中的内容2.2工程结构3.条件编

从入门到进阶讲解Python自动化Playwright实战指南

《从入门到进阶讲解Python自动化Playwright实战指南》Playwright是针对Python语言的纯自动化工具,它可以通过单个API自动执行Chromium,Firefox和WebKit... 目录Playwright 简介核心优势安装步骤观点与案例结合Playwright 核心功能从零开始学习

使用Python绘制3D堆叠条形图全解析

《使用Python绘制3D堆叠条形图全解析》在数据可视化的工具箱里,3D图表总能带来眼前一亮的效果,本文就来和大家聊聊如何使用Python实现绘制3D堆叠条形图,感兴趣的小伙伴可以了解下... 目录为什么选择 3D 堆叠条形图代码实现:从数据到 3D 世界的搭建核心代码逐行解析细节优化应用场景:3D 堆叠图

深度解析Python装饰器常见用法与进阶技巧

《深度解析Python装饰器常见用法与进阶技巧》Python装饰器(Decorator)是提升代码可读性与复用性的强大工具,本文将深入解析Python装饰器的原理,常见用法,进阶技巧与最佳实践,希望可... 目录装饰器的基本原理函数装饰器的常见用法带参数的装饰器类装饰器与方法装饰器装饰器的嵌套与组合进阶技巧

从基础到进阶详解Pandas时间数据处理指南

《从基础到进阶详解Pandas时间数据处理指南》Pandas构建了完整的时间数据处理生态,核心由四个基础类构成,Timestamp,DatetimeIndex,Period和Timedelta,下面我... 目录1. 时间数据类型与基础操作1.1 核心时间对象体系1.2 时间数据生成技巧2. 时间索引与数据

使用Python获取JS加载的数据的多种实现方法

《使用Python获取JS加载的数据的多种实现方法》在当今的互联网时代,网页数据的动态加载已经成为一种常见的技术手段,许多现代网站通过JavaScript(JS)动态加载内容,这使得传统的静态网页爬取... 目录引言一、动态 网页与js加载数据的原理二、python爬取JS加载数据的方法(一)分析网络请求1

QT6中绘制UI的两种方法详解与示例代码

《QT6中绘制UI的两种方法详解与示例代码》Qt6提供了两种主要的UI绘制技术:​​QML(QtMeta-ObjectLanguage)​​和​​C++Widgets​​,这两种技术各有优势,适用于不... 目录一、QML 技术详解1.1 QML 简介1.2 QML 的核心概念1.3 QML 示例:简单按钮

VSCode中配置node.js的实现示例

《VSCode中配置node.js的实现示例》本文主要介绍了VSCode中配置node.js的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一.node.js下载安装教程二.配置npm三.配置环境变量四.VSCode配置五.心得一.no

Python使用Matplotlib绘制3D曲面图详解

《Python使用Matplotlib绘制3D曲面图详解》:本文主要介绍Python使用Matplotlib绘制3D曲面图,在Python中,使用Matplotlib库绘制3D曲面图可以通过mpl... 目录准备工作绘制简单的 3D 曲面图绘制 3D 曲面图添加线框和透明度控制图形视角Matplotlib

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的