本文主要是介绍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机柜的进阶绘制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!