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

相关文章

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2

JS 实现复制到剪贴板的几种方式小结

《JS实现复制到剪贴板的几种方式小结》本文主要介绍了JS实现复制到剪贴板的几种方式小结,包括ClipboardAPI和document.execCommand这两种方法,具有一定的参考价值,感兴趣的... 目录一、Clipboard API相关属性方法二、document.execCommand优点:缺点:

Python进阶之Excel基本操作介绍

《Python进阶之Excel基本操作介绍》在现实中,很多工作都需要与数据打交道,Excel作为常用的数据处理工具,一直备受人们的青睐,本文主要为大家介绍了一些Python中Excel的基本操作,希望... 目录概述写入使用 xlwt使用 XlsxWriter读取修改概述在现实中,很多工作都需要与数据打交

使用Python绘制蛇年春节祝福艺术图

《使用Python绘制蛇年春节祝福艺术图》:本文主要介绍如何使用Python的Matplotlib库绘制一幅富有创意的“蛇年有福”艺术图,这幅图结合了数字,蛇形,花朵等装饰,需要的可以参考下... 目录1. 绘图的基本概念2. 准备工作3. 实现代码解析3.1 设置绘图画布3.2 绘制数字“2025”3.3

使用Python绘制可爱的招财猫

《使用Python绘制可爱的招财猫》招财猫,也被称为“幸运猫”,是一种象征财富和好运的吉祥物,经常出现在亚洲文化的商店、餐厅和家庭中,今天,我将带你用Python和matplotlib库从零开始绘制一... 目录1. 为什么选择用 python 绘制?2. 绘图的基本概念3. 实现代码解析3.1 设置绘图画

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

Python绘制土地利用和土地覆盖类型图示例详解

《Python绘制土地利用和土地覆盖类型图示例详解》本文介绍了如何使用Python绘制土地利用和土地覆盖类型图,并提供了详细的代码示例,通过安装所需的库,准备地理数据,使用geopandas和matp... 目录一、所需库的安装二、数据准备三、绘制土地利用和土地覆盖类型图四、代码解释五、其他可视化形式1.

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math

使用Vue.js报错:ReferenceError: “Vue is not defined“ 的原因与解决方案

《使用Vue.js报错:ReferenceError:“Vueisnotdefined“的原因与解决方案》在前端开发中,ReferenceError:Vueisnotdefined是一个常见... 目录一、错误描述二、错误成因分析三、解决方案1. 检查 vue.js 的引入方式2. 验证 npm 安装3.